"""
UI related code for dialogs used by Mu.
Copyright (c) 2015-2017 Nicholas H.Tollervey and others (see the AUTHORS file).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import (QVBoxLayout, QListWidget, QLabel, QListWidgetItem,
QDialog, QDialogButtonBox, QPlainTextEdit,
QTabWidget, QWidget, QCheckBox, QLineEdit)
from mu.resources import load_icon
logger = logging.getLogger(__name__)
[docs]
class ModeItem(QListWidgetItem):
"""
Represents an available mode listed for selection.
"""
def __init__(self, name, description, icon, parent=None):
super().__init__(parent)
self.name = name
self.description = description
self.icon = icon
text = "{}\n{}".format(name, description)
self.setText(text)
self.setIcon(load_icon(self.icon))
[docs]
class ModeSelector(QDialog):
"""
Defines a UI for selecting the mode for Mu.
"""
def __init__(self, parent=None):
super().__init__(parent)
def setup(self, modes, current_mode):
self.setMinimumSize(600, 400)
self.setWindowTitle(_('Select Mode'))
widget_layout = QVBoxLayout()
label = QLabel(_('Please select the desired mode then click "OK". '
'Otherwise, click "Cancel".'))
label.setWordWrap(True)
widget_layout.addWidget(label)
self.setLayout(widget_layout)
self.mode_list = QListWidget()
self.mode_list.itemDoubleClicked.connect(self.select_and_accept)
widget_layout.addWidget(self.mode_list)
self.mode_list.setIconSize(QSize(48, 48))
for name, item in modes.items():
if not item.is_debugger:
litem = ModeItem(item.name, item.description, item.icon,
self.mode_list)
if item.icon == current_mode:
self.mode_list.setCurrentItem(litem)
self.mode_list.sortItems()
instructions = QLabel(_('Change mode at any time by clicking '
'the "Mode" button containing Mu\'s logo.'))
instructions.setWordWrap(True)
widget_layout.addWidget(instructions)
button_box = QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
widget_layout.addWidget(button_box)
[docs]
def select_and_accept(self):
"""
Handler for when an item is double-clicked.
"""
self.accept()
[docs]
def get_mode(self):
"""
Return details of the newly selected mode.
"""
if self.result() == QDialog.Accepted:
return self.mode_list.currentItem().icon
else:
raise RuntimeError('Mode change cancelled.')
[docs]
class AdminDialog(QDialog):
"""
Displays administrative related information and settings (logs, environment
variables etc...).
"""
def __init__(self, parent=None):
super().__init__(parent)
def setup(self, log, settings):
self.setMinimumSize(600, 400)
self.setWindowTitle(_('Mu Administration'))
widget_layout = QVBoxLayout()
self.setLayout(widget_layout)
self.tabs = QTabWidget()
widget_layout.addWidget(self.tabs)
button_box = QDialogButtonBox(QDialogButtonBox.Ok)
button_box.accepted.connect(self.accept)
widget_layout.addWidget(button_box)
# Tabs
self.log_widget = LogWidget()
self.log_widget.setup(log)
self.tabs.addTab(self.log_widget, _("Current Log"))
self.envar_widget = EnvironmentVariablesWidget()
self.envar_widget.setup(settings.get('envars', ''))
self.tabs.addTab(self.envar_widget, _('Python3 Environment'))
self.log_widget.log_text_area.setFocus()
self.microbit_widget = MicrobitSettingsWidget()
self.microbit_widget.setup(settings.get('minify', False),
settings.get('microbit_runtime', ''))
self.tabs.addTab(self.microbit_widget, _('BBC micro:bit Settings'))
[docs]
def settings(self):
"""
Return a dictionary representation of the raw settings information
generated by this dialog. Such settings will need to be processed /
checked in the "logic" layer of Mu.
"""
return {
'envars': self.envar_widget.text_area.toPlainText(),
'minify': self.microbit_widget.minify.isChecked(),
'microbit_runtime': self.microbit_widget.runtime_path.text(),
}
[docs]
class FindReplaceDialog(QDialog):
"""
Display a dialog for getting:
* A term to find,
* An optional value to replace the search term,
* A flag to indicate if the user wishes to replace all.
"""
def __init__(self, parent=None):
super().__init__(parent)
def setup(self, find=None, replace=None, replace_flag=False):
self.setMinimumSize(600, 200)
self.setWindowTitle(_('Find / Replace'))
widget_layout = QVBoxLayout()
self.setLayout(widget_layout)
# Find.
find_label = QLabel(_('Find:'))
self.find_term = QLineEdit()
self.find_term.setText(find)
widget_layout.addWidget(find_label)
widget_layout.addWidget(self.find_term)
# Replace
replace_label = QLabel(_('Replace (optional):'))
self.replace_term = QLineEdit()
self.replace_term.setText(replace)
widget_layout.addWidget(replace_label)
widget_layout.addWidget(self.replace_term)
# Global replace.
self.replace_all_flag = QCheckBox(_('Replace all?'))
self.replace_all_flag.setChecked(replace_flag)
widget_layout.addWidget(self.replace_all_flag)
button_box = QDialogButtonBox(QDialogButtonBox.Ok |
QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
widget_layout.addWidget(button_box)
[docs]
def find(self):
"""
Return the value the user entered to find.
"""
return self.find_term.text()
[docs]
def replace(self):
"""
Return the value the user entered for replace.
"""
return self.replace_term.text()
[docs]
def replace_flag(self):
"""
Return the value of the global replace flag.
"""
return self.replace_all_flag.isChecked()