def paint(self, painter, option, index): """Colours waypoints with a minor waypoint number (i.e. intermediate waypoints generated by the flight performance service) in red. """ wpnumber_minor = index.model().waypoint_data( index.row()).wpnumber_minor if wpnumber_minor is not None and wpnumber_minor > 0: newpalette = QtGui.QPalette(option.palette) colour = QtGui.QColor(170, 0, 0) # dark red newpalette.setColor(QtGui.QPalette.Text, colour) colour = QtGui.QColor(255, 255, 0) # yellow newpalette.setColor(QtGui.QPalette.HighlightedText, colour) option.palette = newpalette QtWidgets.QItemDelegate.paint(self, painter, option, index)
def __init__(self, parent=None, settings_dict=None, wms_connected=False): """ Arguments: parent -- Qt widget that is parent to this widget. settings_dict -- dictionary containing topview options. """ super(MSS_TV_MapAppearanceDialog, self).__init__(parent) self.setupUi(self) if settings_dict is None: settings_dict = {"draw_graticule": True, "draw_coastlines": True, "fill_waterbodies": True, "fill_continents": True, "draw_flighttrack": True, "label_flighttrack": True, "colour_water": (0, 0, 0, 0), "colour_land": (0, 0, 0, 0), "colour_ft_vertices": (0, 0, 0, 0), "colour_ft_waypoints": (0, 0, 0, 0)} settings_dict["fill_waterbodies"] = True # removing water bodies does not work properly self.wms_connected = wms_connected # check parent.wms_connected to disable cbFillWaterBodies and cbFillContinents if self.wms_connected: self.cbFillContinents.setChecked(False) self.cbFillWaterBodies.setChecked(False) self.cbFillContinents.setEnabled(False) self.cbFillContinents.setStyleSheet("color: black") self.cbFillWaterBodies.setStyleSheet("color: black") else: self.cbFillWaterBodies.setChecked(settings_dict["fill_waterbodies"]) self.cbFillWaterBodies.setEnabled(False) self.cbFillContinents.setChecked(settings_dict["fill_continents"]) self.cbFillContinents.setEnabled(True) self.cbDrawGraticule.setChecked(settings_dict["draw_graticule"]) self.cbDrawCoastlines.setChecked(settings_dict["draw_coastlines"]) self.cbDrawFlightTrack.setChecked(settings_dict["draw_flighttrack"]) self.cbLabelFlightTrack.setChecked(settings_dict["label_flighttrack"]) for button, ids in [(self.btWaterColour, "colour_water"), (self.btLandColour, "colour_land"), (self.btWaypointsColour, "colour_ft_waypoints"), (self.btVerticesColour, "colour_ft_vertices")]: palette = QtGui.QPalette(button.palette()) colour = QtGui.QColor() colour.setRgbF(*settings_dict[ids]) palette.setColor(QtGui.QPalette.Button, colour) button.setPalette(palette) # Connect colour button signals. self.btWaterColour.clicked.connect(functools.partial(self.setColour, "water")) self.btLandColour.clicked.connect(functools.partial(self.setColour, "land")) self.btWaypointsColour.clicked.connect(functools.partial(self.setColour, "ft_waypoints")) self.btVerticesColour.clicked.connect(functools.partial(self.setColour, "ft_vertices"))
def __init__(self, parent=None, view=None): """ Arguments: parent -- Qt widget that is parent to this widget. view -- reference to mpl canvas class """ super(RemoteSensingControlWidget, self).__init__(parent) self.setupUi(self) self.view = view self.load = Loader(MSS_CONFIG_PATH, verbose=False) self.planets = self.load('de421.bsp') self.timescale = self.load.timescale(builtin=True) # don't download files, use shipped files button = self.btTangentsColour palette = QtGui.QPalette(button.palette()) colour = QtGui.QColor() colour.setRgbF(1, 0, 0, 1) palette.setColor(QtGui.QPalette.Button, colour) button.setPalette(palette) self.dsbTangentHeight.setValue(10.) self.dsbObsAngleAzimuth.setValue(90.) self.dsbObsAngleElevation.setValue(-1.0) # update plot on every value change self.cbDrawTangents.stateChanged.connect(self.update_settings) self.cbShowSolarAngle.stateChanged.connect(self.update_settings) self.btTangentsColour.clicked.connect(self.set_tangentpoint_colour) self.dsbTangentHeight.valueChanged.connect(self.update_settings) self.dsbObsAngleAzimuth.valueChanged.connect(self.update_settings) self.dsbObsAngleElevation.valueChanged.connect(self.update_settings) self.cbSolarBody.currentIndexChanged.connect(self.update_settings) self.cbSolarAngleType.currentIndexChanged.connect(self.update_settings) self.lbSolarCmap.setText( "Solar angle colours, dark to light: reds (0-15), violets (15-45), greens (45-180)" ) self.solar_cmap = ListedColormap([(1.00, 0.00, 0.00, 1.0), (1.00, 0.45, 0.00, 1.0), (1.00, 0.75, 0.00, 1.0), (0.47, 0.10, 1.00, 1.0), (0.72, 0.38, 1.00, 1.0), (1.00, 0.55, 1.00, 1.0), (0.00, 0.70, 0.00, 1.0), (0.33, 0.85, 0.33, 1.0), (0.65, 1.00, 0.65, 1.0)]) self.solar_norm = BoundaryNorm( [0, 5, 10, 15, 25, 35, 45, 90, 135, 180], self.solar_cmap.N) self.update_settings()
def open_customize_kml_dialog(self): file = self.listWidget.currentItem().text() # Set the colour of the Colour button to the colour of specific KML plot if self.dict_files[file]["color"] is not None: palette = QtGui.QPalette(self.dialog.pushButton_colour.palette()) colour = QtGui.QColor() colour.setRgbF(*self.set_color(file)) palette.setColor(QtGui.QPalette.Button, colour) self.dialog.pushButton_colour.setPalette(palette) # Set the linewidth value to the linewidth of specific KML plot if self.dict_files[file]["linewidth"] is not None: self.dialog.dsb_linewidth.setValue(self.set_linewidth(file)) self.dialog.show()
class Test_MSS_SV_OptionsDialog(object): def setup(self): self.application = QtWidgets.QApplication(sys.argv) self.window = tv.MSS_SV_OptionsDialog() self.window.show() QtWidgets.QApplication.processEvents() QtTest.QTest.qWaitForWindowExposed(self.window) QtWidgets.QApplication.processEvents() def teardown(self): self.window.hide() QtWidgets.QApplication.processEvents() self.application.quit() QtWidgets.QApplication.processEvents() @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_show(self, mockcrit): assert mockcrit.critical.call_count == 0 @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_get(self, mockcrit): self.window.get_settings() assert mockcrit.critical.call_count == 0 @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_addLevel(self, mockcrit): QtTest.QTest.mouseClick(self.window.btAdd, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mockcrit.critical.call_count == 0 @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_removeLevel(self, mockcrit): QtTest.QTest.mouseClick(self.window.btDelete, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mockcrit.critical.call_count == 0 def test_getFlightLevels(self): levels = self.window.get_flight_levels() assert all(x == y for x, y in zip(levels, [300, 320, 340])) QtTest.QTest.mouseClick(self.window.btAdd, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() levels = self.window.get_flight_levels() assert all(x == y for x, y in zip(levels, [0, 300, 320, 340])) @mock.patch("mslib.msui.mss_qt.QtWidgets.QColorDialog.getColor", return_value=QtGui.QColor()) def test_setColour(self, mockdlg): QtTest.QTest.mouseClick(self.window.btFillColour, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mockdlg.call_count == 1
def __init__(self, parent=None, settings_dict=None): """ Arguments: parent -- Qt widget that is parent to this widget. settings_dict -- dictionary containing sideview options. """ _translate = QtCore.QCoreApplication.translate super(MSS_SV_OptionsDialog, self).__init__(parent) self.setupUi(self) default_settings_dict = { "vertical_extent": (1050, 180), "vertical_axis": "pressure", "flightlevels": [300, 320, 340], "draw_flightlevels": True, "draw_flighttrack": True, "fill_flighttrack": True, "label_flighttrack": True, "colour_ft_vertices": (0, 0, 0, 0), "colour_ft_waypoints": (0, 0, 0, 0), "colour_ft_fill": (0, 0, 0, 0), "draw_ceiling": True, "colour_ceiling": (0.1, 0.5, 0.1, 0), } suffixes = [' hpa', ' km', ' hft'] if settings_dict is not None: default_settings_dict.update(settings_dict) settings_dict = default_settings_dict self.setBotTopLimits(settings_dict["vertical_axis"]) self.sbPbot.setValue(settings_dict["vertical_extent"][0]) self.sbPtop.setValue(settings_dict["vertical_extent"][1]) flightlevels = settings_dict["flightlevels"] self.tableWidget.setRowCount(len(flightlevels)) flightlevels.sort() for i, level in enumerate(flightlevels): tableitem = QtWidgets.QTableWidgetItem(str(int(level))) self.tableWidget.setItem(i, 0, tableitem) for i in range(self.cbVerticalAxis.count()): if self.cbVerticalAxis.itemText(i) == settings_dict["vertical_axis"]: self.cbVerticalAxis.setCurrentIndex(i) self.sbPbot.setSuffix(_translate("SideViewOptionsDialog", suffixes[i])) self.sbPtop.setSuffix(_translate("SideViewOptionsDialog", suffixes[i])) self.cbDrawFlightLevels.setChecked(settings_dict["draw_flightlevels"]) self.cbDrawFlightTrack.setChecked(settings_dict["draw_flighttrack"]) self.cbFillFlightTrack.setChecked(settings_dict["fill_flighttrack"]) self.cbLabelFlightTrack.setChecked(settings_dict["label_flighttrack"]) self.cbDrawCeiling.setChecked(settings_dict["draw_ceiling"]) for button, ids in [(self.btFillColour, "colour_ft_fill"), (self.btWaypointsColour, "colour_ft_waypoints"), (self.btVerticesColour, "colour_ft_vertices"), (self.btCeilingColour, "colour_ceiling")]: palette = QtGui.QPalette(button.palette()) colour = QtGui.QColor() colour.setRgbF(*settings_dict[ids]) palette.setColor(QtGui.QPalette.Button, colour) button.setPalette(palette) # Connect colour button signals. self.cbVerticalAxis.view().pressed.connect(self.verticalunitsclicked) self.btFillColour.clicked.connect(functools.partial(self.setColour, "ft_fill")) self.btWaypointsColour.clicked.connect(functools.partial(self.setColour, "ft_waypoints")) self.btVerticesColour.clicked.connect(functools.partial(self.setColour, "ft_vertices")) self.btCeilingColour.clicked.connect(functools.partial(self.setColour, "ceiling")) self.btAdd.clicked.connect(self.addItem) self.btDelete.clicked.connect(self.deleteSelected) self.tableWidget.itemChanged.connect(self.itemChanged)
def __init__(self, parent=None, view=None): super(KMLOverlayControlWidget, self).__init__(parent) self.setupUi(self) self.view = view # canvas self.kml = None self.patch = None # patch refers to plottings on the map self.dict_files = { } # Dictionary of files added; key : patch , color , linewidth # Connect slots and signals. self.btSelectFile.clicked.connect(self.get_file) self.pushButton_remove.clicked.connect(self.remove_file) self.pushButton_select_all.clicked.connect(self.select_all) self.pushButton_unselect_all.clicked.connect(self.unselect_all) self.pushButton_merge.clicked.connect(self.merge_file) self.labelStatusBar.setText( "Status: Click on Add KML Files to get started.") self.dialog = CustomizeKMLWidget( self) # create object of dialog UI Box self.listWidget.itemDoubleClicked.connect( self.open_customize_kml_dialog) self.dialog.pushButton_colour.clicked.connect(self.select_color) self.listWidget.itemChanged.connect( self.load_file) # list of files in ListWidget self.settings_tag = "kmldock" settings = load_settings_qsettings( self.settings_tag, { "filename": "", "linewidth": 5, "colour": (0, 0, 0, 1), "saved_files": {} }) # initial settings self.directory_location = settings["filename"] self.dialog.dsb_linewidth.setValue(settings["linewidth"]) # Restore previously opened files if settings["saved_files"] is not None: delete_files = [] # list to store non-existing files self.dict_files = settings["saved_files"] for file in self.dict_files: if os.path.isfile(file) is True: self.create_list_item(file) else: delete_files.append(file) # add non-existent files to list logging.info(file + " does not exist in the directory anymore") for file in delete_files: del self.dict_files[ file] # remove non-existent files from dictionary self.load_file() palette = QtGui.QPalette(self.dialog.pushButton_colour.palette()) colour = QtGui.QColor() colour.setRgbF(*settings["colour"]) palette.setColor(QtGui.QPalette.Button, colour) self.dialog.pushButton_colour.setPalette( palette) # sets the last colour before closing KML Overlay self.dialog.dsb_linewidth.valueChanged.connect(self.select_linewidth)
class Test_KmlOverlayDockWidget(object): def setup(self): self.application = QtWidgets.QApplication(sys.argv) self.view = mock.Mock() self.view.map = mock.Mock(side_effect=lambda x, y: (x, y)) self.view.map.plot = mock.Mock(return_value=[mock.Mock()]) self.window = kd.KMLOverlayControlWidget(view=self.view) self.window.show() QtWidgets.QApplication.processEvents() QtTest.QTest.qWaitForWindowExposed(self.window) # start load test self.window.select_all() self.window.remove_file() QtWidgets.QApplication.processEvents() def teardown(self): QtWidgets.QApplication.processEvents() self.application.quit() QtWidgets.QApplication.processEvents() self.window.close() if os.path.exists(save_kml): os.remove(save_kml) def select_file(self, file): # Utility function for single file path = fs.path.join(sample_path, "kml", file) filename = (path, ) # converted to tuple self.window.select_file(filename) QtWidgets.QApplication.processEvents() return path def select_files(self): # Utility function for multiple files for sample in [ "folder.kml", "line.kml", "color.kml", "style.kml", "features.kml" ]: path = fs.path.join(sample_path, "kml", sample) filename = (path, ) # converted to tuple self.window.select_file(filename) QtWidgets.QApplication.processEvents() @mock.patch("mslib.msui.kmloverlay_dockwidget.get_open_filenames", return_value=[fs.path.join(sample_path, "kml", "line.kml")]) def test_get_file(self, mockopen): # Tests opening of QFileDialog QtTest.QTest.mouseClick(self.window.btSelectFile, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mockopen.call_count == 1 @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_select_file(self, mockbox): """ Test All geometries and styles are being parsed without crashing """ index = 0 assert self.window.listWidget.count() == 0 for sample in [ "folder.kml", "line.kml", "color.kml", "style.kml", "features.kml", "geometry_collection.kml", "Multilinestrings.kml", "polygon_inner.kml", "World_Map.kml" ]: path = self.select_file(sample) QtTest.QTest.qWait(250) assert self.window.listWidget.item( index).checkState() == QtCore.Qt.Checked index = index + 1 assert self.window.directory_location == path assert mockbox.critical.call_count == 0 assert self.window.listWidget.count() == index assert len(self.window.dict_files) == index assert self.window.patch is not None self.window.select_all() self.window.remove_file() @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") def test_select_file_error(self, mockbox): """ Test that program mitigates loading a non-existing file """ # load a non existing path self.window.select_all() self.window.remove_file() path = fs.path.join(sample_path, "satellite_tracks", "satellite_predictor.txt") filename = (path, ) # converted to tuple self.window.select_file(filename) QtWidgets.QApplication.processEvents() assert mockbox.critical.call_count == 1 self.window.listWidget.clear() self.window.dict_files = {} def test_remove_file(self): """ Test removing all files except one """ self.select_files() QtWidgets.QApplication.processEvents() self.window.listWidget.item(0).setCheckState(QtCore.Qt.Unchecked) QtTest.QTest.mouseClick(self.window.pushButton_remove, QtCore.Qt.LeftButton) assert self.window.listWidget.count() == 1 assert len(self.window.dict_files) == 1 self.window.select_all() self.window.remove_file() def test_remove_all_files(self): """ Test removing all files """ self.select_files() QtWidgets.QApplication.processEvents() assert self.window.listWidget.count() == 5 QtTest.QTest.mouseClick(self.window.pushButton_remove, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert self.window.listWidget.count() == 0 # No items in list assert self.window.dict_files == {} # Dictionary should be empty assert self.window.patch is None # Patch should be None @mock.patch("mslib.msui.mss_qt.QtWidgets.QMessageBox") @mock.patch("mslib.msui.kmloverlay_dockwidget.get_save_filename", return_value=save_kml) def test_merge_file(self, mocksave, mockbox): """ Test merging files into a single file without crashing """ self.select_files() QtWidgets.QApplication.processEvents() QtTest.QTest.mouseClick(self.window.pushButton_merge, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mocksave.call_count == 1 assert os.path.exists(save_kml) @mock.patch("mslib.msui.mss_qt.QtWidgets.QColorDialog.getColor", return_value=QtGui.QColor()) def test_customize_kml(self, mock_colour_dialog): """ Test opening Customize KML Dialogue and checking specific file gets desired linewidth and colour """ path = self.select_file("line.kml") # selects file and returns path assert self.window.listWidget.count() == 1 item = self.window.listWidget.item(0) rect = self.window.listWidget.visualItemRect(item) # in testing, need to add mouseclick before double click QtTest.QTest.mouseClick(self.window.listWidget.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) QtWidgets.QApplication.processEvents() # Double click feature QtTest.QTest.mouseDClick(self.window.listWidget.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) QtWidgets.QApplication.processEvents() # Clicking on Push Button Colour QtTest.QTest.mouseClick(self.window.dialog.pushButton_colour, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert mock_colour_dialog.call_count == 1 # Testing the Double Spin Box self.window.dialog.dsb_linewidth.setValue(3) assert self.window.dialog.dsb_linewidth.value() == 3 # clicking on OK Button okWidget = self.window.dialog.buttonBox.button( self.window.dialog.buttonBox.Ok) QtTest.QTest.mouseClick(okWidget, QtCore.Qt.LeftButton) QtWidgets.QApplication.processEvents() assert self.window.dict_files[path]["color"] == self.window.get_color() assert self.window.dict_files[path]["linewidth"] == 3 self.window.remove_file() assert self.window.listWidget.count() == 0 def test_check_uncheck(self): """ Tests 'Displays plot on map when file is checked' and vice versa """ self.select_file("line.kml") assert self.window.listWidget.item(0).checkState() == QtCore.Qt.Checked assert len(self.window.patch.patches) == 1 self.window.listWidget.item(0).setCheckState(QtCore.Qt.Unchecked) assert self.window.listWidget.item( 0).checkState() == QtCore.Qt.Unchecked assert len(self.window.patch.patches) == 0 self.window.select_all() self.window.remove_file() # Matplotlib Plots Testing def test_kml_patches(self): """ Tests the type of patches plotted by each Test Sample File """ self.select_file("line.kml") assert len( self.window.patch.patches) == 1 # 1 LineString Geometry Patch self.window.remove_file() self.select_file("folder.kml") assert len( self.window.patch.patches) == 3 # 1 Point, 1 Polygon, 1 Text Patch self.window.remove_file() self.select_file("color.kml") assert len(self.window.patch.patches) == 1 # 1 Polygon Patch self.window.remove_file() self.select_file("style.kml") assert len(self.window.patch.patches ) == 4 # 1 Point, 1 Text, 1 Polygon, 1 LineString Patch self.window.remove_file() self.select_file("features.kml") assert len(self.window.patch.patches ) == 17 # 3 Points, 11 LineStrings, 3 Polygons Patch self.window.remove_file() self.select_file("polygon_inner.kml") assert len(self.window.patch.patches) == 5 # 5 Polygons Patch self.window.remove_file() self.select_file("Multilinestrings.kml") assert len(self.window.patch.patches) == 10 # 10 LineStrings Patch self.window.remove_file() self.select_file("geometry_collection.kml") assert len( self.window.patch.patches) == 3 # 1 Point, 1 Text, 1 Polygon Patch self.window.remove_file() self.select_file("World_Map.kml") assert len(self.window.patch.patches) == 292 # 292 Polygons Patch self.window.remove_file()