Package node_manager_fkie :: Module settings_widget
[frames] | no frames]

Source Code for Module node_manager_fkie.settings_widget

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Fraunhofer nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  import os 
 33  from datetime import datetime 
 34   
 35  from python_qt_binding import QtGui 
 36  from python_qt_binding import QtCore 
 37  from python_qt_binding import loadUi 
 38   
 39  import node_manager_fkie as nm 
 40   
 41  from .settings_model import SettingsModel, SettingsValueItem 
 42   
 43   
44 -class SettingsWidget(QtGui.QDockWidget):
45 ''' 46 Settings widget to handle the settings changes. The changes will direct change 47 the settings of the GUI. 48 ''' 49
50 - def __init__(self, parent=None):
51 ''' 52 Creates the window, connects the signals and init the class. 53 ''' 54 QtGui.QDockWidget.__init__(self, parent) 55 # load the UI file 56 settings_dock_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'SettingsDockWidget.ui') 57 loadUi(settings_dock_file, self) 58 # initialize the settings view model 59 self.settings_model = SettingsModel() 60 self.settings_proxyModel = QtGui.QSortFilterProxyModel(self) 61 self.settings_proxyModel.setSourceModel(self.settings_model) 62 self.settingsTreeView.setModel(self.settings_proxyModel) 63 self.settingsTreeView.setAlternatingRowColors(True) 64 for i, (name, width) in enumerate(SettingsModel.header): 65 self.settingsTreeView.setColumnWidth(i, width) 66 self.item_delegate = ItemDelegate() 67 self.item_delegate.settings_path_changed_signal.connect(self.reload_settings) 68 self.settingsTreeView.setItemDelegateForColumn(1, self.item_delegate) 69 self.reload_settings()
70
71 - def reload_settings(self):
72 ''' 73 Load the current settings data into the model. The settings itself will not 74 be loaded. 75 ''' 76 settings = {'Default user:' : ({ 77 'value' : nm.settings().default_user, 78 'settings' : nm.settings(), 79 'attrname' : 'default_user', 80 'value_default' : nm.settings().USER_DEFAULT, 81 'tooltip' : '<p>The user used for ssh connection to remote hosts</p>' 82 },), 83 'Launch history length:' : ({ 84 'value' : nm.settings().launch_history_length, 85 'settings' : nm.settings(), 86 'attrname' : 'launch_history_length', 87 'value_default' : nm.settings().LAUNCH_HISTORY_LENGTH, 88 'value_min' : 0, 89 'value_max' : 25, 90 'tooltip' : '<p>The count of recent ' 91 'loaded launch files displayed in the root ' 92 'of the <span style=" font-weight:600;">launch ' 93 'files</span> view.</p>' 94 },), 95 'Param history length:' : ({ 96 'value' : nm.settings().param_history_length, 97 'settings' : nm.settings(), 98 'attrname' : 'param_history_length', 99 'value_default' : nm.settings().PARAM_HISTORY_LENGTH, 100 'value_min' : 0, 101 'value_max' : 25, 102 'tooltip' : '<p>The count of parameters stored which ' 103 'are entered in a parameter dialog (Launch file arguments, ' 104 'paramter server, publishing to a topic, service call)</p>' 105 },), 106 107 'Settings path:' : ({ 108 'value' : nm.settings().cfg_path, 109 'settings' : nm.settings(), 110 'attrname' : 'cfg_path', 111 'edit_type' : SettingsValueItem.EDIT_TYPE_FOLDER, 112 'value_default' : nm.settings().CFG_PATH, 113 'tooltip' : '' 114 },), 115 'Robot icon path:' : ({ 116 'value' : nm.settings().robots_path, 117 'settings' : nm.settings(), 118 'attrname' : 'robots_path', 119 'edit_type' : SettingsValueItem.EDIT_TYPE_FOLDER, 120 'value_default' : nm.settings().ROBOTS_DIR, 121 'tooltip' : '<p>The path to the folder with robot images ' 122 '(<span style=" font-weight:600;">.png</span>).' 123 'The images with robot name will be displayed in the ' 124 'info bar.</p>' 125 },), 126 'Show files extentions:' : ({ 127 'value' : ', '.join(nm.settings().launch_view_file_ext), 128 'settings' : nm.settings(), 129 'attrname' : 'launch_view_file_ext', 130 'value_default' : ', '.join(nm.settings().LAUNCH_VIEW_EXT), 131 'tooltip' : '<p>Files that are displayed next to Launch ' 132 'files in the <span style="font-weight:600;">' 133 'launch files</span> view</p>' 134 },), 135 'Store window layout:' : ({ 136 'value' : nm.settings().store_geometry, 137 'settings' : nm.settings(), 138 'attrname' : 'store_geometry', 139 'value_default' : nm.settings().STORE_GEOMETRY, 140 'tooltip' : '' 141 },) 142 } 143 self.settings_model.init_settings(settings) 144 # self.settingsTreeView.setSortingEnabled(True) 145 self.settingsTreeView.sortByColumn(0, QtCore.Qt.AscendingOrder) 146 self.settingsTreeView.expandAll()
147 148
149 -class ItemDelegate(QtGui.QStyledItemDelegate):
150 ''' 151 This ItemDelegate provides editors for different setting types in settings view. 152 ''' 153 154 settings_path_changed_signal = QtCore.Signal() 155 156 reload_settings = False 157
158 - def createEditor(self, parent, option, index):
159 ''' 160 Creates a editor in the TreeView depending on type of the settings data. 161 ''' 162 item = self._itemFromIndex(index) 163 if item.edit_type() == SettingsValueItem.EDIT_TYPE_AUTODETECT: 164 if isinstance(item.value(), bool): 165 box = QtGui.QCheckBox(parent) 166 box.setFocusPolicy(QtCore.Qt.StrongFocus) 167 box.setAutoFillBackground(True) 168 box.stateChanged.connect(self.edit_finished) 169 return box 170 elif isinstance(item.value(), int): 171 box = QtGui.QSpinBox(parent) 172 box.setValue(item.value()) 173 if not item.value_min() is None: 174 box.setMinimum(item.value_min()) 175 if not item.value_max() is None: 176 box.setMaximum(item.value_max()) 177 return box 178 elif item.edit_type() == SettingsValueItem.EDIT_TYPE_FOLDER: 179 editor = PathEditor(item.value(), parent) 180 editor.editing_finished_signal.connect(self.edit_finished) 181 return editor 182 return QtGui.QStyledItemDelegate.createEditor(self, parent, option, index)
183 184 # def setEditorData(self, editor, index): 185 # print "setEditorData" 186 # QtGui.QStyledItemDelegate.setEditorData(self, editor, index) 187 188 # def updateEditorGeometry(self, editor, option, index): 189 # print "updateEditorGeometry", option.rect.width() 190 # editor.setMaximumSize(option.rect.width(), option.rect.height()) 191 # QtGui.QStyledItemDelegate.updateEditorGeometry(self, editor, option, index) 192
193 - def setModelData(self, editor, model, index):
194 if isinstance(editor, PathEditor): 195 cfg_path = nm.settings().cfg_path 196 model.setData(index, editor.path) 197 self.reload_settings = (cfg_path != nm.settings().cfg_path) 198 else: 199 QtGui.QStyledItemDelegate.setModelData(self, editor, model, index)
200
201 - def sizeHint(self, option, index):
202 ''' 203 Determines and returns the size of the text after the format. 204 @see: U{http://www.pyside.org/docs/pyside/PySide/QtGui/QAbstractItemDelegate.html#PySide.QtGui.QAbstractItemDelegate} 205 ''' 206 options = QtGui.QStyleOptionViewItemV4(option) 207 self.initStyleOption(options,index) 208 return QtCore.QSize(options.rect.width(), 25)
209
210 - def edit_finished(self, arg=None):
211 editor = self.sender() 212 # The commitData signal must be emitted when we've finished editing 213 # and need to write our changed back to the model. 214 self.commitData.emit(editor) 215 self.closeEditor.emit(editor, QtGui.QAbstractItemDelegate.NoHint) 216 if self.reload_settings: 217 self.reload_settings = False 218 self.settings_path_changed_signal.emit()
219
220 - def _itemFromIndex(self, index):
221 if isinstance(index.model(), QtGui.QSortFilterProxyModel): 222 sindex = index.model().mapToSource(index) 223 return index.model().sourceModel().itemFromIndex(sindex) 224 else: 225 return index.model().itemFromIndex(index)
226 227
228 -class PathEditor(QtGui.QWidget):
229 ''' 230 This is a path editor used as ItemDeligate in settings view. This editor 231 provides an additional button for directory selection dialog. 232 ''' 233 234 editing_finished_signal = QtCore.Signal() 235
236 - def __init__(self, path, parent=None):
237 QtGui.QWidget.__init__(self, parent) 238 self.path = path 239 self._layout = QtGui.QHBoxLayout(self) 240 self._layout.setContentsMargins(0, 0, 0, 0) 241 self._layout.setSpacing(0) 242 self._button = QtGui.QPushButton('...') 243 self._button.setMaximumSize(QtCore.QSize(24, 20)) 244 self._button.clicked.connect(self._on_path_select_clicked) 245 self._layout.addWidget(self._button) 246 self._lineedit = QtGui.QLineEdit(path) 247 self._lineedit.returnPressed.connect(self._on_editing_finished) 248 self._layout.addWidget(self._lineedit) 249 self.setLayout(self._layout) 250 self.setFocusProxy(self._button) 251 self.setAutoFillBackground(True)
252
253 - def _on_path_select_clicked(self):
254 # Workaround for QtGui.QFileDialog.getExistingDirectory because it do not 255 # select the configuration folder in the dialog 256 self.dialog = QtGui.QFileDialog(self, caption='Select a new settings folder') 257 self.dialog.setOption(QtGui.QFileDialog.HideNameFilterDetails, True) 258 self.dialog.setFileMode(QtGui.QFileDialog.Directory) 259 self.dialog.setDirectory(self.path) 260 if self.dialog.exec_(): 261 fileNames = self.dialog.selectedFiles() 262 dir = fileNames[0] 263 if os.path.isfile(dir): 264 dir = os.path.basename(dir) 265 self._lineedit.setText(dir) 266 self.path = dir 267 self.editing_finished_signal.emit()
268
269 - def _on_editing_finished(self):
270 if self._lineedit.text(): 271 self.path = self._lineedit.text() 272 self.editing_finished_signal.emit()
273