forked from openlp/openlp
head
This commit is contained in:
commit
ce96bb6179
@ -662,7 +662,7 @@ class AdvancedTab(SettingsTab):
|
|||||||
u'background-color: %s' % self.defaultColor)
|
u'background-color: %s' % self.defaultColor)
|
||||||
|
|
||||||
def onDefaultBrowseButtonClicked(self):
|
def onDefaultBrowseButtonClicked(self):
|
||||||
file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(),
|
file_filters = u'%s;;%s (*.*)' % (get_images_filter(),
|
||||||
UiStrings().AllFiles)
|
UiStrings().AllFiles)
|
||||||
filename = QtGui.QFileDialog.getOpenFileName(self,
|
filename = QtGui.QFileDialog.getOpenFileName(self,
|
||||||
translate('OpenLP.AdvancedTab', 'Open File'), '',
|
translate('OpenLP.AdvancedTab', 'Open File'), '',
|
||||||
|
@ -219,7 +219,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
|||||||
self,translate('ImagePlugin.ExceptionDialog',
|
self,translate('ImagePlugin.ExceptionDialog',
|
||||||
'Select Attachment'),
|
'Select Attachment'),
|
||||||
SettingsManager.get_last_dir(u'exceptions'),
|
SettingsManager.get_last_dir(u'exceptions'),
|
||||||
u'%s (*.*) (*)' % UiStrings().AllFiles)
|
u'%s (*.*)' % UiStrings().AllFiles)
|
||||||
log.info(u'New files(s) %s', unicode(files))
|
log.info(u'New files(s) %s', unicode(files))
|
||||||
if files:
|
if files:
|
||||||
self.fileAttachment = unicode(files)
|
self.fileAttachment = unicode(files)
|
||||||
|
@ -42,7 +42,8 @@ from PyQt4 import QtCore, QtGui
|
|||||||
from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \
|
from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, \
|
||||||
check_directory_exists
|
check_directory_exists
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
from openlp.core.utils import get_web_page, AppLocation, get_filesystem_encoding
|
from openlp.core.utils import get_web_page, AppLocation, join_url, \
|
||||||
|
get_filesystem_encoding
|
||||||
from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
|
from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -57,6 +58,9 @@ class ThemeScreenshotThread(QtCore.QThread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
themes = self.parent().config.get(u'themes', u'files')
|
themes = self.parent().config.get(u'themes', u'files')
|
||||||
themes = themes.split(u',')
|
themes = themes.split(u',')
|
||||||
|
themes_dir = self.parent().config.get(u'themes', u'directory')
|
||||||
|
tmp_dir = os.path.join(unicode(gettempdir(), get_filesystem_encoding()),
|
||||||
|
u'openlp')
|
||||||
config = self.parent().config
|
config = self.parent().config
|
||||||
for theme in themes:
|
for theme in themes:
|
||||||
# Stop if the wizard has been cancelled.
|
# Stop if the wizard has been cancelled.
|
||||||
@ -65,9 +69,9 @@ class ThemeScreenshotThread(QtCore.QThread):
|
|||||||
title = config.get(u'theme_%s' % theme, u'title')
|
title = config.get(u'theme_%s' % theme, u'title')
|
||||||
filename = config.get(u'theme_%s' % theme, u'filename')
|
filename = config.get(u'theme_%s' % theme, u'filename')
|
||||||
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
|
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
|
||||||
urllib.urlretrieve(u'%s%s' % (self.parent().web, screenshot),
|
urllib.urlretrieve(join_url(self.parent().baseurl,
|
||||||
os.path.join(unicode(gettempdir(), get_filesystem_encoding()),
|
themes_dir, screenshot),
|
||||||
u'openlp', screenshot))
|
os.path.join(tmp_dir, screenshot))
|
||||||
item = QtGui.QListWidgetItem(title, self.parent().themesListWidget)
|
item = QtGui.QListWidgetItem(title, self.parent().themesListWidget)
|
||||||
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(filename))
|
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(filename))
|
||||||
item.setCheckState(QtCore.Qt.Unchecked)
|
item.setCheckState(QtCore.Qt.Unchecked)
|
||||||
@ -85,13 +89,22 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
QtGui.QWizard.__init__(self, parent)
|
QtGui.QWizard.__init__(self, parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.screens = screens
|
self.screens = screens
|
||||||
# check to see if we have web access
|
|
||||||
self.web = u'http://openlp.org/files/frw/'
|
|
||||||
self.config = SafeConfigParser()
|
self.config = SafeConfigParser()
|
||||||
|
# The following url should contain 'download.cfg' or redirect OpenLP
|
||||||
|
# to the right url of 'download.cfg' file.
|
||||||
|
# 'download.cfg' file contains definitions for everything that is
|
||||||
|
# available for download into OpenLP in FirstTimeWizard.
|
||||||
|
self.web = u'http://openlp.org/files/frw/'
|
||||||
|
# Base url for dowloading resource files (songs, themes, bibles).
|
||||||
|
# These files could be hosted on different places and thus the base
|
||||||
|
# url is defined in 'download.cfg' file.
|
||||||
|
self.baseurl = None
|
||||||
|
# Check to see if we have web access
|
||||||
self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg'))
|
self.webAccess = get_web_page(u'%s%s' % (self.web, u'download.cfg'))
|
||||||
if self.webAccess:
|
if self.webAccess:
|
||||||
files = self.webAccess.read()
|
files = self.webAccess.read()
|
||||||
self.config.readfp(io.BytesIO(files))
|
self.config.readfp(io.BytesIO(files))
|
||||||
|
self.baseurl = self.config.get(u'general', u'base url')
|
||||||
self.updateScreenListCombo()
|
self.updateScreenListCombo()
|
||||||
self.downloadCancelled = False
|
self.downloadCancelled = False
|
||||||
self.downloading = unicode(translate('OpenLP.FirstTimeWizard',
|
self.downloading = unicode(translate('OpenLP.FirstTimeWizard',
|
||||||
@ -123,7 +136,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
# Check if this is a re-run of the wizard.
|
# Check if this is a re-run of the wizard.
|
||||||
self.hasRunWizard = Settings().value(
|
self.hasRunWizard = Settings().value(
|
||||||
u'general/has run wizard', QtCore.QVariant(False)).toBool()
|
u'general/has run wizard', QtCore.QVariant(False)).toBool()
|
||||||
# Sort out internet access for downloads
|
# Sort out internet access for downloads.
|
||||||
if self.webAccess:
|
if self.webAccess:
|
||||||
songs = self.config.get(u'songs', u'languages')
|
songs = self.config.get(u'songs', u'languages')
|
||||||
songs = songs.split(u',')
|
songs = songs.split(u',')
|
||||||
@ -280,6 +293,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
Download a file given a URL. The file is retrieved in chunks, giving
|
Download a file given a URL. The file is retrieved in chunks, giving
|
||||||
the ability to cancel the download at any point.
|
the ability to cancel the download at any point.
|
||||||
"""
|
"""
|
||||||
|
log.debug(u'Downloading %s' % url)
|
||||||
block_count = 0
|
block_count = 0
|
||||||
block_size = 4096
|
block_size = 4096
|
||||||
urlfile = urllib2.urlopen(url)
|
urlfile = urllib2.urlopen(url)
|
||||||
@ -348,13 +362,18 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
self.max_progress = 0
|
self.max_progress = 0
|
||||||
self.finishButton.setVisible(False)
|
self.finishButton.setVisible(False)
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
|
# Directory name appended to base download url as the name
|
||||||
|
# is found in download.cfg file.
|
||||||
|
songs_dir = unicode(self.config.get(u'songs', u'directory'), u'utf8')
|
||||||
|
bibles_dir = unicode(self.config.get(u'bibles', u'directory'), u'utf8')
|
||||||
|
themes_dir = unicode(self.config.get(u'themes', u'directory'), u'utf8')
|
||||||
# Loop through the songs list and increase for each selected item
|
# Loop through the songs list and increase for each selected item
|
||||||
for i in xrange(self.songsListWidget.count()):
|
for i in xrange(self.songsListWidget.count()):
|
||||||
Receiver.send_message(u'openlp_process_events')
|
Receiver.send_message(u'openlp_process_events')
|
||||||
item = self.songsListWidget.item(i)
|
item = self.songsListWidget.item(i)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.Checked:
|
||||||
filename = item.data(QtCore.Qt.UserRole).toString()
|
filename = item.data(QtCore.Qt.UserRole).toString()
|
||||||
size = self._getFileSize(u'%s%s' % (self.web, filename))
|
size = self._getFileSize(join_url(self.baseurl, songs_dir, filename))
|
||||||
self.max_progress += size
|
self.max_progress += size
|
||||||
# Loop through the Bibles list and increase for each selected item
|
# Loop through the Bibles list and increase for each selected item
|
||||||
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
||||||
@ -363,7 +382,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
||||||
filename = item.data(0, QtCore.Qt.UserRole).toString()
|
filename = item.data(0, QtCore.Qt.UserRole).toString()
|
||||||
size = self._getFileSize(u'%s%s' % (self.web, filename))
|
size = self._getFileSize(join_url(self.baseurl, bibles_dir, filename))
|
||||||
self.max_progress += size
|
self.max_progress += size
|
||||||
iterator += 1
|
iterator += 1
|
||||||
# Loop through the themes list and increase for each selected item
|
# Loop through the themes list and increase for each selected item
|
||||||
@ -372,7 +391,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
item = self.themesListWidget.item(i)
|
item = self.themesListWidget.item(i)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.Checked:
|
||||||
filename = item.data(QtCore.Qt.UserRole).toString()
|
filename = item.data(QtCore.Qt.UserRole).toString()
|
||||||
size = self._getFileSize(u'%s%s' % (self.web, filename))
|
size = self._getFileSize(join_url(self.baseurl, themes_dir, filename))
|
||||||
self.max_progress += size
|
self.max_progress += size
|
||||||
if self.max_progress:
|
if self.max_progress:
|
||||||
# Add on 2 for plugins status setting plus a "finished" point.
|
# Add on 2 for plugins status setting plus a "finished" point.
|
||||||
@ -448,6 +467,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
unicode(gettempdir(), get_filesystem_encoding()), u'openlp')
|
unicode(gettempdir(), get_filesystem_encoding()), u'openlp')
|
||||||
bibles_destination = AppLocation.get_section_data_path(u'bibles')
|
bibles_destination = AppLocation.get_section_data_path(u'bibles')
|
||||||
themes_destination = AppLocation.get_section_data_path(u'themes')
|
themes_destination = AppLocation.get_section_data_path(u'themes')
|
||||||
|
# Directory name appended to base download url as the name
|
||||||
|
# is found in download.cfg file.
|
||||||
|
songs_dir = unicode(self.config.get(u'songs', u'directory'), u'utf8')
|
||||||
|
bibles_dir = unicode(self.config.get(u'bibles', u'directory'), u'utf8')
|
||||||
|
themes_dir = unicode(self.config.get(u'themes', u'directory'), u'utf8')
|
||||||
# Download songs
|
# Download songs
|
||||||
for i in xrange(self.songsListWidget.count()):
|
for i in xrange(self.songsListWidget.count()):
|
||||||
item = self.songsListWidget.item(i)
|
item = self.songsListWidget.item(i)
|
||||||
@ -457,7 +481,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
self.previous_size = 0
|
self.previous_size = 0
|
||||||
destination = os.path.join(songs_destination,
|
destination = os.path.join(songs_destination,
|
||||||
unicode(filename))
|
unicode(filename))
|
||||||
self.urlGetFile(u'%s%s' % (self.web, filename), destination)
|
self.urlGetFile(join_url(self.baseurl, songs_dir, filename),
|
||||||
|
destination)
|
||||||
# Download Bibles
|
# Download Bibles
|
||||||
bibles_iterator = QtGui.QTreeWidgetItemIterator(
|
bibles_iterator = QtGui.QTreeWidgetItemIterator(
|
||||||
self.biblesTreeWidget)
|
self.biblesTreeWidget)
|
||||||
@ -467,7 +492,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
bible = unicode(item.data(0, QtCore.Qt.UserRole).toString())
|
bible = unicode(item.data(0, QtCore.Qt.UserRole).toString())
|
||||||
self._incrementProgressBar(self.downloading % bible, 0)
|
self._incrementProgressBar(self.downloading % bible, 0)
|
||||||
self.previous_size = 0
|
self.previous_size = 0
|
||||||
self.urlGetFile(u'%s%s' % (self.web, bible),
|
self.urlGetFile(join_url(self.baseurl, bibles_dir, bible),
|
||||||
os.path.join(bibles_destination, bible))
|
os.path.join(bibles_destination, bible))
|
||||||
bibles_iterator += 1
|
bibles_iterator += 1
|
||||||
# Download themes
|
# Download themes
|
||||||
@ -477,7 +502,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
|||||||
theme = unicode(item.data(QtCore.Qt.UserRole).toString())
|
theme = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||||
self._incrementProgressBar(self.downloading % theme, 0)
|
self._incrementProgressBar(self.downloading % theme, 0)
|
||||||
self.previous_size = 0
|
self.previous_size = 0
|
||||||
self.urlGetFile(u'%s%s' % (self.web, theme),
|
self.urlGetFile(join_url(self.baseurl, themes_dir, theme),
|
||||||
os.path.join(themes_destination, theme))
|
os.path.join(themes_destination, theme))
|
||||||
# Set Default Display
|
# Set Default Display
|
||||||
if self.displayComboBox.currentIndex() != -1:
|
if self.displayComboBox.currentIndex() != -1:
|
||||||
|
@ -536,7 +536,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
|||||||
Background Image button pushed.
|
Background Image button pushed.
|
||||||
"""
|
"""
|
||||||
images_filter = get_images_filter()
|
images_filter = get_images_filter()
|
||||||
images_filter = u'%s;;%s (*.*) (*)' % (
|
images_filter = u'%s;;%s (*.*)' % (
|
||||||
images_filter, UiStrings().AllFiles)
|
images_filter, UiStrings().AllFiles)
|
||||||
filename = QtGui.QFileDialog.getOpenFileName(self,
|
filename = QtGui.QFileDialog.getOpenFileName(self,
|
||||||
translate('OpenLP.ThemeWizard', 'Select Image'), u'',
|
translate('OpenLP.ThemeWizard', 'Select Image'), u'',
|
||||||
|
@ -180,8 +180,8 @@ class Ui_ThemeWizard(object):
|
|||||||
self.lineSpacingLabel = QtGui.QLabel(self.mainAreaPage)
|
self.lineSpacingLabel = QtGui.QLabel(self.mainAreaPage)
|
||||||
self.lineSpacingLabel.setObjectName(u'LineSpacingLabel')
|
self.lineSpacingLabel.setObjectName(u'LineSpacingLabel')
|
||||||
self.lineSpacingSpinBox = QtGui.QSpinBox(self.mainAreaPage)
|
self.lineSpacingSpinBox = QtGui.QSpinBox(self.mainAreaPage)
|
||||||
self.lineSpacingSpinBox.setMinimum(-50)
|
self.lineSpacingSpinBox.setMinimum(-250)
|
||||||
self.lineSpacingSpinBox.setMaximum(50)
|
self.lineSpacingSpinBox.setMaximum(250)
|
||||||
self.lineSpacingSpinBox.setObjectName(u'LineSpacingSpinBox')
|
self.lineSpacingSpinBox.setObjectName(u'LineSpacingSpinBox')
|
||||||
self.mainAreaLayout.addRow(self.lineSpacingLabel,
|
self.mainAreaLayout.addRow(self.lineSpacingLabel,
|
||||||
self.lineSpacingSpinBox)
|
self.lineSpacingSpinBox)
|
||||||
|
@ -37,6 +37,7 @@ import re
|
|||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
import sys
|
import sys
|
||||||
import urllib2
|
import urllib2
|
||||||
|
import urlparse
|
||||||
|
|
||||||
from openlp.core.lib.settings import Settings
|
from openlp.core.lib.settings import Settings
|
||||||
|
|
||||||
@ -364,6 +365,23 @@ def get_images_filter():
|
|||||||
return IMAGES_FILTER
|
return IMAGES_FILTER
|
||||||
|
|
||||||
|
|
||||||
|
def join_url(base, *args):
|
||||||
|
"""
|
||||||
|
Join one or more url components with the base url.
|
||||||
|
|
||||||
|
``base``
|
||||||
|
Base url containing top level domain.
|
||||||
|
e.g. http://www.example.org
|
||||||
|
|
||||||
|
``args``
|
||||||
|
url components to be appended to the base url.
|
||||||
|
"""
|
||||||
|
# Remove leading and trailing slash from components.
|
||||||
|
# Also ensure QString is converted to unicode().
|
||||||
|
args = [unicode(x).strip('/') for x in args]
|
||||||
|
return urlparse.urljoin(base, '/'.join(args))
|
||||||
|
|
||||||
|
|
||||||
def split_filename(path):
|
def split_filename(path):
|
||||||
"""
|
"""
|
||||||
Return a list of the parts in a given path.
|
Return a list of the parts in a given path.
|
||||||
|
@ -62,7 +62,7 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
self.onNewPrompt = translate('ImagePlugin.MediaItem',
|
self.onNewPrompt = translate('ImagePlugin.MediaItem',
|
||||||
'Select Image(s)')
|
'Select Image(s)')
|
||||||
file_formats = get_images_filter()
|
file_formats = get_images_filter()
|
||||||
self.onNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats,
|
self.onNewFileMasks = u'%s;;%s (*.*)' % (file_formats,
|
||||||
UiStrings().AllFiles)
|
UiStrings().AllFiles)
|
||||||
self.replaceAction.setText(UiStrings().ReplaceBG)
|
self.replaceAction.setText(UiStrings().ReplaceBG)
|
||||||
self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
|
self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
|
||||||
|
@ -283,7 +283,6 @@ class Ui_EditSongDialog(object):
|
|||||||
self.bottomLayout.setObjectName(u'bottomLayout')
|
self.bottomLayout.setObjectName(u'bottomLayout')
|
||||||
self.warningLabel = QtGui.QLabel(editSongDialog)
|
self.warningLabel = QtGui.QLabel(editSongDialog)
|
||||||
self.warningLabel.setObjectName(u'warningLabel')
|
self.warningLabel.setObjectName(u'warningLabel')
|
||||||
self.warningLabel.setVisible(False)
|
|
||||||
self.bottomLayout.addWidget(self.warningLabel)
|
self.bottomLayout.addWidget(self.warningLabel)
|
||||||
self.buttonBox = create_button_box(editSongDialog, u'buttonBox',
|
self.buttonBox = create_button_box(editSongDialog, u'buttonBox',
|
||||||
[u'cancel', u'save'])
|
[u'cancel', u'save'])
|
||||||
@ -355,9 +354,10 @@ class Ui_EditSongDialog(object):
|
|||||||
translate('SongsPlugin.EditSongForm', '&Remove'))
|
translate('SongsPlugin.EditSongForm', '&Remove'))
|
||||||
self.audioRemoveAllButton.setText(
|
self.audioRemoveAllButton.setText(
|
||||||
translate('SongsPlugin.EditSongForm', 'Remove &All'))
|
translate('SongsPlugin.EditSongForm', 'Remove &All'))
|
||||||
self.warningLabel.setText(
|
self.notAlllVersesUsed = translate('SongsPlugin.EditSongForm', '<strong>Warning:</strong>'
|
||||||
translate('SongsPlugin.EditSongForm', '<strong>Warning:</strong>'
|
' Not all of the verses are in use.')
|
||||||
' Not all of the verses are in use.'))
|
self.noVerseOrder = translate('SongsPlugin.EditSongForm', '<strong>Warning:</strong>'
|
||||||
|
' You have not entered a verse order.')
|
||||||
|
|
||||||
def editSongDialogComboBox(parent, name):
|
def editSongDialogComboBox(parent, name):
|
||||||
"""
|
"""
|
||||||
|
@ -349,6 +349,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
|
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
|
||||||
# Hide or show the preview button.
|
# Hide or show the preview button.
|
||||||
self.previewButton.setVisible(preview)
|
self.previewButton.setVisible(preview)
|
||||||
|
# Check if all verse tags are used.
|
||||||
|
self.onVerseOrderTextChanged(self.verseOrderEdit.text())
|
||||||
|
|
||||||
def tagRows(self):
|
def tagRows(self):
|
||||||
"""
|
"""
|
||||||
@ -608,7 +610,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||||||
for verse in verses:
|
for verse in verses:
|
||||||
if not verse in order:
|
if not verse in order:
|
||||||
verses_not_used.append(verse)
|
verses_not_used.append(verse)
|
||||||
self.warningLabel.setVisible(len(verses_not_used) > 0)
|
label_text = u''
|
||||||
|
if not self.verseOrderEdit.text():
|
||||||
|
label_text = self.noVerseOrder
|
||||||
|
elif verses_not_used:
|
||||||
|
label_text = self.notAlllVersesUsed
|
||||||
|
self.warningLabel.setText(label_text)
|
||||||
|
|
||||||
def __extractVerseOrder(self, verse_order):
|
def __extractVerseOrder(self, verse_order):
|
||||||
order = []
|
order = []
|
||||||
|
Loading…
Reference in New Issue
Block a user