class ClipManagerApp(object): def __init__(self): app = QApplication(sys.argv) self.window = QMainWindow() self.ui = Ui_MainWindow() self.ui.setupUi(self.window) self.window.connect(self.ui.action, QtCore.SIGNAL('triggered()'), self.on_open) self.window.connect(self.ui.action_3, QtCore.SIGNAL('triggered()'), self.on_exit) self.window.connect(self.ui.action_4, QtCore.SIGNAL('triggered()'), self.on_execute) self.ui.textEdit.setLexer(Qsci.QsciLexerPython()) self.ui.textEdit.setText("""#y=x ##or #yl = [] #for i in xl: # yl.append(i+"i") """ ) self.window.show() sys.exit(app.exec_()) def on_open(self): fname = QFileDialog.getOpenFileName(self.window, 'Open file', '/') if fname != "": f = open(fname, 'r') with f: data = f.read() self.ui.textEdit.setText(data) def on_exit(self): self.window.close() def on_execute(self): script_text = str(self.ui.textEdit.text()) # print 'script is:',script_text source_text = str(self.ui.textEdit_2.text()) source_text = source_text.replace('\r', '') xl = source_text.split('\n') #Set source text to x so script can use x as source text as well x = source_text y = None t = None exec script_text #print y if y is None: y = '\n'.join(yl) #print y self.ui.textEdit_3.setText(y) """
class loginWindow(LoginWin): def __init__(self): self.setupUI() def setupUI(self): self.window = QMainWindow() qss = QtCore.QFile("qss/loginWindow.qss") qss.open(QtCore.QFile.ReadOnly) qssStr = QtCore.QLatin1String(qss.readAll()) self.setupUi(self.window) #self.pushButton.click.connect() self.window.show() self.window.setStyleSheet(qssStr) #self.pushButton.clicked.connect(self.clo) def clo(self): self.window.close()
def close(self): """Exit the program""" self.minimizeOnClose = False QMainWindow.close(self)
class TestLayerTree(object): """ Unit tests for the layer_tree_widget class """ def setup_method(self, method): self.data = example_data.test_data() self.hub = core.hub.Hub() self.collect = core.data_collection.DataCollection(list(self.data)) self.widget = LayerTreeWidget() self.win = QMainWindow() self.win.setCentralWidget(self.widget) self.widget.setup(self.collect, self.hub) for key, value in self.widget._actions.items(): self.__setattr__("%s_action" % key, value) def teardown_method(self, method): self.win.close() del self.win def select_layers(self, *layers): items = [self.widget[l] for l in layers] for item in self.widget.layerTree.items(): layer = self.widget[item] item.setSelected(layer in layers) assert set(items) == set(self.widget.layerTree.selectedItems()) def remove_layer(self, layer): """ Remove a layer via the widget remove button """ widget_item = self.widget[layer] self.widget.layerTree.setCurrentItem(widget_item) QTest.mousePress(self.widget.layerRemoveButton, Qt.LeftButton) QTest.mouseRelease(self.widget.layerRemoveButton, Qt.LeftButton) def add_layer(self, layer=None): """ Add a layer through a hub message """ layer = layer or core.Data() self.widget.data_collection.append(layer) assert layer in self.widget.data_collection assert layer in self.widget return layer def layer_present(self, layer): """ Test that a layer exists in the widget """ return self.widget.is_layer_present(layer) and \ layer.data in self.widget.data_collection def test_current_layer_method_correct(self): layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) assert self.widget.current_layer() is layer def test_add(self): """ Test that a layer exists in widget once added """ data = core.Data() assert not self.layer_present(data) self.add_layer(data) assert self.layer_present(data) def test_remove_layer(self): """ Test that widget remove button works properly """ layer = self.add_layer() self.remove_layer(layer) assert not self.layer_present(layer) assert not layer in self.widget.data_collection def test_remove_subset_layer(self): """ Test that widget remove button works properly on subsets""" layer = self.add_layer() subset = layer.new_subset() assert self.layer_present(subset) self.remove_layer(subset) assert not self.layer_present(subset) def test_empty_removal_does_nothing(self): """ Make sure widgets are only removed when selected """ layer = self.add_layer() widget_item = self.widget[layer] self.widget.layerTree.setCurrentItem(widget_item) self.widget.layerTree.setItemSelected(widget_item, False) QTest.mousePress(self.widget.layerRemoveButton, Qt.LeftButton) assert self.layer_present(layer) @patch('glue.qt.widgets.layer_tree_widget.LinkEditor') def test_link_data(self, le): layer = self.add_layer() self.select_layers(layer) self.link_action.trigger() assert le.update_links.call_count == 1 def test_check_signal(self): layer = self.add_layer() sc = MagicMock() self.widget._layer_check_changed.connect(sc.catch) item = self.widget[layer] item.setCheckState(0, Qt.Unchecked) sc.catch.assert_called_once_with(layer, False) def test_new_subset_action(self): """ new action creates a new subset """ layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) self.new_action.trigger() assert len(layer.subsets) == 1 def test_duplicate_subset_action(self): """ duplicate action creates duplicate subset """ layer = self.add_layer() layer.new_subset() item = self.widget[layer.subsets[0]] self.widget.layerTree.setCurrentItem(item) ct = len(layer.subsets) self.duplicate_action.trigger() assert len(layer.subsets) == ct + 1 def test_copy_paste_subset_action(self): layer = self.add_layer() layer.new_subset() item = self.widget[layer.subsets[0]] self.widget.layerTree.setCurrentItem(item) self.copy_action.trigger() sub = layer.new_subset() item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) state0 = sub.subset_state self.paste_action.trigger() assert sub.subset_state is not state0 def setup_two_subset_selection(self): layer = self.add_layer() s1 = layer.new_subset() s2 = layer.new_subset() item1 = self.widget[s1] item2 = self.widget[s2] self.widget.layerTree.setCurrentItem(item1, 0, QItemSelectionModel.Clear) self.widget.layerTree.setCurrentItem(item1, 0, QItemSelectionModel.Toggle) self.widget.layerTree.setCurrentItem(item2, 0, QItemSelectionModel.Toggle) assert len(self.widget.layerTree.selectedItems()) == 2 return layer def _test_combine(self, action, state): layer = self.setup_two_subset_selection() old_subsets = set(layer.subsets) action.trigger() new_subsets = set(layer.subsets) diff = list(old_subsets ^ new_subsets) assert len(diff) == 1 assert isinstance(diff[0].subset_state, state) def test_or_combine(self): self._test_combine(self.or_action, core.subset.OrState) def test_and_combine(self): self._test_combine(self.and_action, core.subset.AndState) def test_xor_combine(self): self._test_combine(self.xor_action, core.subset.XorState) def test_invert(self): layer = self.add_layer() sub = layer.new_subset() item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) self.invert_action.trigger() assert isinstance(sub.subset_state, core.subset.InvertState) def test_actions_enabled_single_subset_selection(self): Clipboard().contents = None layer = self.add_layer() item = self.widget[layer.new_subset()] self.widget.layerTree.setCurrentItem(item) assert not self.or_action.isEnabled() assert not self.and_action.isEnabled() assert not self.xor_action.isEnabled() assert self.new_action.isEnabled() assert self.copy_action.isEnabled() assert self.duplicate_action.isEnabled() assert not self.paste_action.isEnabled() assert self.invert_action.isEnabled() assert self.clear_action.isEnabled() def test_actions_enabled_single_data_selection(self): layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) assert not self.or_action.isEnabled() assert not self.and_action.isEnabled() assert not self.xor_action.isEnabled() assert self.new_action.isEnabled() assert not self.copy_action.isEnabled() assert not self.duplicate_action.isEnabled() assert not self.paste_action.isEnabled() assert not self.invert_action.isEnabled() assert not self.clear_action.isEnabled() def test_actions_enabled_multi_subset_selection(self): layer = self.setup_two_subset_selection() assert self.or_action.isEnabled() assert self.and_action.isEnabled() assert self.xor_action.isEnabled() assert not self.new_action.isEnabled() assert not self.copy_action.isEnabled() assert not self.duplicate_action.isEnabled() assert not self.paste_action.isEnabled() assert not self.invert_action.isEnabled() assert not self.clear_action.isEnabled() def test_checkable_toggle(self): self.widget.set_checkable(True) assert self.widget.is_checkable() self.widget.set_checkable(False) assert not self.widget.is_checkable() def test_edit_layer_label(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_label' with patch(pth) as edit_layer_label: layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 0) self.widget._actions['label'].trigger() edit_layer_label.assert_called_once_with(layer) def test_edit_layer_color(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_color' with patch(pth) as edit_layer_color: layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 0) self.widget._actions['color'].trigger() edit_layer_color.assert_called_once_with(layer) def test_edit_layer_symbol(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_symbol' with patch(pth) as edit_layer_symbol: layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 0) self.widget._actions['marker'].trigger() edit_layer_symbol.assert_called_once_with(layer) def test_edit_layer_point_size(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_point_size' with patch(pth) as edit_layer_point_size: layer = self.add_layer() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 0) self.widget._actions['size'].trigger() edit_layer_point_size.assert_called_once_with(layer) def test_load_data(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.data_wizard' with patch(pth) as wizard: wizard.return_value = [self.data[0]] self.widget._load_data() assert self.layer_present(self.data[0]) def test_load_data_doesnt_double_add(self): """bugfix""" pth = 'glue.qt.widgets.layer_tree_widget.qtutil.data_wizard' with patch(pth) as wizard: wizard.return_value = [core.Data()] ct0 = self.widget.layerTree.topLevelItemCount() self.widget._load_data() assert self.widget.layerTree.topLevelItemCount() == ct0 + 1 def test_clear_subset(self): layer = self.add_layer() sub = layer.new_subset() item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) dummy_state = MagicMock() sub.subset_state = dummy_state self.clear_action.trigger() assert not sub.subset_state == dummy_state def test_single_selection_updates_editable(self): self.widget.bind_selection_to_edit_subset() layer = self.add_layer() subset = layer.new_subset() subset2 = layer.new_subset() assert layer.edit_subset != [subset] self.select_layers(subset) assert layer.edit_subset == [subset] def test_multi_selection_updates_editable(self): """Selection disables edit_subset for all other data""" self.widget.bind_selection_to_edit_subset() layer = self.add_layer() subset = layer.new_subset() layer2 = self.add_layer() subset2 = layer2.new_subset() subset3 = layer2.new_subset() self.select_layers(subset, subset2) assert subset in layer.edit_subset assert subset2 in layer2.edit_subset assert subset3 not in layer2.edit_subset def test_selection_updates_on_add(self): layer = self.add_layer() assert self.widget.selected_layers() == [layer] sub = layer.new_subset() assert self.widget.selected_layers() == [sub]
def close(self): """Exits the program.""" self.minimizeOnClose = False QMainWindow.close(self)
class TestScatterWidget(object): def setup_method(self, method): self.app = QApplication(sys.argv) self.hub = core.hub.Hub() self.data = example_data.test_data() self.collect = core.data_collection.DataCollection() self.widget = ScatterWidget(self.collect) self.win = QMainWindow() self.win.setCentralWidget(self.widget) self.connect_to_hub() self.win.show() def tearDown(self): self.win.close() del self.win del self.app def connect_to_hub(self): self.widget.register_to_hub(self.hub) self.collect.register_to_hub(self.hub) def add_layer_via_hub(self): layer = self.data[0] self.collect.append(layer) return layer def add_layer_via_method(self): layer = self.data[0] self.collect.append(layer) self.widget.add_layer(layer) return layer def plot_data(self, layer): """ Return the data bounds for a given layer (data or subset) Output format: [xmin, xmax], [ymin, ymax] """ client = self.widget.client data = client.managers[layer].get_data() xmin = data[:, 0].min() xmax = data[:, 0].max() ymin = data[:, 1].min() ymax = data[:, 1].max() return [xmin, xmax], [ymin, ymax] def plot_limits(self): """ Return the plot limits Output format [xmin, xmax], [ymin, ymax] """ ax = self.widget.client.ax xlim = ax.get_xlim() ylim = ax.get_ylim() return xlim, ylim return def assert_layer_inside_limits(self, layer): """Assert that points of a layer are within plot limits """ xydata = self.plot_data(layer) xylimits = self.plot_limits() assert xydata[0][0] >= xylimits[0][0] assert xydata[1][0] >= xylimits[1][0] assert xydata[0][1] <= xylimits[0][1] assert xydata[1][1] <= xylimits[1][1] def set_layer_checkbox(self, layer, state): item = self.widget.ui.layerTree[layer] item.setCheckState(0, state) def is_layer_present(self, layer): if not self.widget.ui.layerTree.is_layer_present(layer): return False return self.widget.client.is_layer_present(layer) def is_layer_visible(self, layer): return self.widget.client.is_visible(layer) def test_rescaled_on_init(self): layer = self.add_layer_via_method() self.assert_layer_inside_limits(layer) def test_hub_data_add_is_ignored(self): layer = self.add_layer_via_hub() assert not self.widget.ui.layerTree.is_layer_present(layer) assert not self.widget.client.is_layer_present(layer) def test_valid_add_data_via_method(self): layer = self.add_layer_via_method() assert self.is_layer_present(layer) def test_add_first_data_updates_combos(self): layer = self.add_layer_via_method() xatt = str(self.widget.ui.xAxisComboBox.currentText()) yatt = str(self.widget.ui.yAxisComboBox.currentText()) assert xatt is not None assert yatt is not None def test_flip_x(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.xFlipCheckBox, Qt.LeftButton) assert self.widget.client.is_xflip() QTest.mouseClick(self.widget.ui.xFlipCheckBox, Qt.LeftButton) assert not self.widget.client.is_xflip() def test_flip_y(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.yFlipCheckBox, Qt.LeftButton) assert self.widget.client.is_yflip() QTest.mouseClick(self.widget.ui.yFlipCheckBox, Qt.LeftButton) assert not self.widget.client.is_yflip() def test_log_x(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.xLogCheckBox, Qt.LeftButton) assert self.widget.client.is_xlog() QTest.mouseClick(self.widget.ui.xLogCheckBox, Qt.LeftButton) assert not self.widget.client.is_xlog() def test_log_y(self): QTest.mouseClick(self.widget.ui.yLogCheckBox, Qt.LeftButton) assert self.widget.client.is_ylog() QTest.mouseClick(self.widget.ui.yLogCheckBox, Qt.LeftButton) assert not self.widget.client.is_ylog() def test_double_add_ignored(self): layer = self.add_layer_via_method() nobj = self.widget.ui.xAxisComboBox.count() layer = self.add_layer_via_method() assert self.widget.ui.xAxisComboBox.count() == nobj def test_subsets_dont_duplicate_fields(self): layer = self.add_layer_via_method() nobj = self.widget.ui.xAxisComboBox.count() subset = layer.new_subset() subset.register() assert subset in self.widget.ui.layerTree assert self.widget.ui.xAxisComboBox.count() == nobj def test_checkboxes_toggle_visbility(self): layer = self.add_layer_via_method() self.set_layer_checkbox(layer, Qt.Unchecked) assert not self.is_layer_visible(layer) self.set_layer_checkbox(layer, Qt.Checked) assert self.is_layer_visible(layer)
class _WebkitRendererHelper(QObject): """This helper class is doing the real work. It is required to allow WebkitRenderer.render() to be called "asynchronously" (but always from Qt's GUI thread). """ def __init__(self, parent): """Copies the properties from the parent (WebkitRenderer) object, creates the required instances of QWebPage, QWebView and QMainWindow and registers some Slots. """ QObject.__init__(self) # Copy properties from parent for key, value in parent.__dict__.items(): setattr(self, key, value) # Create and connect required PyQt4 objects self._page = QWebPage() self._view = QWebView() self._view.setPage(self._page) self._window = QMainWindow() self._window.setCentralWidget(self._view) # Import QWebSettings for key, value in self.qWebSettings.iteritems(): self._page.settings().setAttribute(key, value) # Connect required event listeners self.connect( self._page, SIGNAL("loadFinished(bool)"), self._on_load_finished ) self.connect( self._page, SIGNAL("loadStarted()"), self._on_load_started ) self.connect( self._page.networkAccessManager(), SIGNAL("sslErrors(QNetworkReply *,const QList<QSslError>&)"), self._on_ssl_errors ) self.connect( self._page.networkAccessManager(), SIGNAL("finished(QNetworkReply *)"), self._on_each_reply ) # The way we will use this, it seems to be unesseccary to have # Scrollbars enabled. self._page.mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff ) self._page.mainFrame().setScrollBarPolicy( Qt.Vertical, Qt.ScrollBarAlwaysOff ) self._page.settings().setUserStyleSheetUrl( QUrl("data:text/css,html,body{overflow-y:hidden !important;}") ) # Show this widget self._window.show() def __del__(self): """Clean up Qt4 objects. """ self._window.close() del self._window del self._view del self._page def render(self, url): """The real worker. Loads the page (_load_page) and awaits the end of the given 'delay'. While it is waiting outstanding QApplication events are processed. After the given delay, the Window or Widget (depends on the value of 'grabWholeWindow' is drawn into a QPixmap and postprocessed (_post_process_image). """ self._load_page(url, self.width, self.height, self.timeout) # Wait for end of timer. In this time, process # other outstanding Qt events. if self.wait > 0: if self.logger: self.logger.debug("Waiting %d seconds " % self.wait) waitToTime = time.time() + self.wait while time.time() < waitToTime and QApplication.hasPendingEvents(): QApplication.processEvents() if self.renderTransparentBackground: # Another possible drawing solution image = QImage(self._page.viewportSize(), QImage.Format_ARGB32) image.fill(QColor(255, 0, 0, 0).rgba()) # http://ariya.blogspot.com/2009/04/transparent-qwebview-and-qwebpage.html palette = self._view.palette() palette.setBrush(QPalette.Base, Qt.transparent) self._page.setPalette(palette) self._view.setAttribute(Qt.WA_OpaquePaintEvent, False) painter = QPainter(image) painter.setBackgroundMode(Qt.TransparentMode) self._page.mainFrame().render(painter) painter.end() else: if self.grabWholeWindow: # Note that this does not fully ensure that the # window still has the focus when the screen is # grabbed. This might result in a race condition. self._view.activateWindow() image = QPixmap.grabWindow(self._window.winId()) else: image = QPixmap.grabWidget(self._window) return self._post_process_image(image) def _load_page(self, url, width, height, timeout): """ This method implements the logic for retrieving and displaying the requested page. """ # This is an event-based application. So we have to wait until # "loadFinished(bool)" raised. cancelAt = time.time() + timeout self.__loading = True self.__loadingResult = False # Default # TODO: fromEncoded() needs to be used in some situations. Some # sort of flag should be passed in to WebkitRenderer maybe? #self._page.mainFrame().load(QUrl.fromEncoded(url)) self._page.mainFrame().load(QUrl(url)) while self.__loading: if timeout > 0 and time.time() >= cancelAt: raise RuntimeError("Request timed out on %s" % url) while QApplication.hasPendingEvents() and self.__loading: QCoreApplication.processEvents() if self.logger: self.logger.debug("Processing result") if not self.__loading_result: if self.logger: self.logger.warning("Failed to load %s" % url) raise BadURLException("Failed to load %s" % url) # Set initial viewport (the size of the "window") size = self._page.mainFrame().contentsSize() if self.logger: self.logger.debug("contentsSize: %s", size) if width > 0: size.setWidth(width) if height > 0: size.setHeight(height) self._window.resize(size) def _post_process_image(self, qImage): """If 'scaleToWidth' or 'scaleToHeight' are set to a value greater than zero this method will scale the image using the method defined in 'scaleRatio'. """ if self.scaleToWidth > 0 or self.scaleToHeight > 0: # Scale this image if self.scaleRatio == 'keep': ratio = Qt.KeepAspectRatio elif self.scaleRatio in ['expand', 'crop']: ratio = Qt.KeepAspectRatioByExpanding else: # 'ignore' ratio = Qt.IgnoreAspectRatio qImage = qImage.scaled( self.scaleToWidth, self.scaleToHeight, ratio ) if self.scaleRatio == 'crop': qImage = qImage.copy( 0, 0, self.scaleToWidth, self.scaleToHeight ) return qImage def _on_each_reply(self, reply): """Logs each requested uri""" self.logger.debug("Received %s" % (reply.url().toString())) # Eventhandler for "loadStarted()" signal def _on_load_started(self): """Slot that sets the '__loading' property to true.""" if self.logger: self.logger.debug("loading started") self.__loading = True # Eventhandler for "loadFinished(bool)" signal def _on_load_finished(self, result): """Slot that sets the '__loading' property to false and stores the result code in '__loading_result'. """ if self.logger: self.logger.debug("loading finished with result %s", result) self.__loading = False self.__loading_result = result # Eventhandler for "sslErrors(QNetworkReply *,const QList<QSslError>&)" # signal. def _on_ssl_errors(self, reply, errors): """Slot that writes SSL warnings into the log but ignores them.""" for e in errors: if self.logger: self.logger.warn("SSL: " + e.errorString()) reply.ignoreSslErrors()
class ClipManagerApp(object): def __init__(self): app = QApplication(sys.argv) self.window = QMainWindow() self.ui = Ui_MainWindow() self.ui.setupUi(self.window) self.window.connect(self.ui.action, QtCore.SIGNAL("triggered()"), self.on_open) self.window.connect(self.ui.action_3, QtCore.SIGNAL("triggered()"), self.on_exit) self.window.connect(self.ui.action_4, QtCore.SIGNAL("triggered()"), self.on_execute) self.ui.textEdit.setLexer(Qsci.QsciLexerPython()) self.ui.textEdit.setText( """#y=x ##or #yl = [] #for i in xl: # yl.append(i+"i") """ ) self.window.show() sys.exit(app.exec_()) def on_open(self): fname = QFileDialog.getOpenFileName(self.window, "Open file", "/") if fname != "": f = open(fname, "r") with f: data = f.read() self.ui.textEdit.setText(data) def on_exit(self): self.window.close() def get_input_text(self): return unicode(self.ui.textEdit_2.text()) def on_execute(self): script_text = str(self.ui.textEdit.text()) # print 'script is:',script_text source_text = self.get_input_text() source_text = source_text.replace("\r", "") xl = source_text.split("\n") # Set source text to x so script can use x as source text as well x = source_text y = None t = None self.ui.textEdit_4.setText("") try: exec script_text # print y if y is None: y = "\n".join(yl) # print y except: import traceback self.ui.textEdit_4.setText(traceback.format_exc()) self.ui.textEdit_3.setText(y) """
class TestLayerTree(object): """ Unit tests for the layer_tree_widget class """ def setup_method(self, method): import sys self.app = QApplication(sys.argv) self.data = example_data.test_data() self.hub = core.hub.Hub() self.collect = core.data_collection.DataCollection(list(self.data)) self.widget = LayerTreeWidget() self.win = QMainWindow() self.win.setCentralWidget(self.widget) def tearDown(self): self.win.close() del self.win del self.app def add_layer_via_method(self): """ Add first layer by invoking method""" self.widget.add_layer(self.data[0]) return self.data[0] def remove_layer_via_button(self, layer): """ Remove a layer via the widget remove button """ widget_item = self.widget[layer] self.widget.layerTree.setCurrentItem(widget_item) QTest.mousePress(self.widget.layerRemoveButton, Qt.LeftButton) def add_layer_via_hub(self): """ Add a layer through a hub message """ self.widget.data_collection = self.collect self.widget.register_to_hub(self.hub) self.collect.register_to_hub(self.hub) layer = self.data[0] self.collect.append(layer) return layer def layer_present(self, layer): """ Test that a layer exists in the widget """ return self.widget.is_layer_present(layer) and \ layer.data in self.widget.data_collection def test_current_layer_method_correct(self): layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) assert self.widget.current_layer() is layer def test_current_layer_null_on_creation(self): assert self.widget.current_layer() is None def test_add_layer_method(self): """ Test that a layer exists once added """ assert not self.layer_present(self.data[0]) layer = self.add_layer_via_method() assert self.layer_present(layer) def test_remove_layer(self): """ Test that widget remove button works properly """ layer = self.add_layer_via_method() self.remove_layer_via_button(layer) assert not self.layer_present(layer) assert not layer in self.widget.data_collection def test_remove_layer_ignored_if_edit_subset(self): layer = self.add_layer_via_method() self.remove_layer_via_button(layer.edit_subset) assert self.layer_present(layer.edit_subset) def test_empty_removal_does_nothing(self): """ Make sure widgets are only removed when selected """ layer = self.add_layer_via_method() widget_item = self.widget[layer] self.widget.layerTree.setCurrentItem(widget_item) self.widget.layerTree.setItemSelected(widget_item, False) QTest.mousePress(self.widget.layerRemoveButton, Qt.LeftButton) assert self.layer_present(layer) def test_add_via_hub_message(self): """ Test that hub messages properly add layers """ layer = self.add_layer_via_hub() assert self.layer_present(layer) def test_remove_via_hub_message(self): """ Test that hub messages properly remove layers """ layer = self.add_layer_via_hub() self.collect.remove(layer) assert not self.layer_present(layer) def test_update_via_hub_message(self): """ Test that hub messages properly update layers """ layer = self.add_layer_via_hub() layer.style.markersize = 999 assert layer in self.widget widget_item = self.widget[layer] assert str(widget_item.text(3)) == "999" def test_data_added_with_subset_add(self): """ Test that subset layers are added properly """ layer = self.data[0] sub = core.subset.Subset(layer) self.widget.add_layer(sub) assert self.layer_present(sub) assert self.layer_present(layer) def test_subsets_added_with_data(self): layer = self.add_layer_via_method() assert self.layer_present(layer.subsets[0]) def test_check_signal(self): layer = self.add_layer_via_method() sc = MagicMock() self.widget._layer_check_changed.connect(sc.catch) item = self.widget[layer] item.setCheckState(0, Qt.Unchecked) sc.catch.assert_called_once_with(layer, False) def test_new_subset_action(self): layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) self.widget._new_action.trigger() assert len(layer.subsets) == 2 def test_duplicate_subset_action(self): layer = self.add_layer_via_method() item = self.widget[layer.subsets[0]] self.widget.layerTree.setCurrentItem(item) self.widget._duplicate_action.trigger() assert len(layer.subsets) == 2 def test_copy_paste_subset_action(self): layer = self.add_layer_via_method() item = self.widget[layer.subsets[0]] self.widget.layerTree.setCurrentItem(item) self.widget._copy_action.trigger() assert self.widget._clipboard is not None sub = layer.new_subset() self.widget.add_layer(sub) item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) state0 = sub.subset_state self.widget._paste_action.trigger() assert sub.subset_state is not state0 def setup_two_subset_selection(self): layer = self.add_layer_via_method() s2 = layer.new_subset() self.widget.add_layer(s2) item1 = self.widget[layer.edit_subset] item2 = self.widget[s2] self.widget.layerTree.setCurrentItem(item1, 0, QItemSelectionModel.Toggle) self.widget.layerTree.setCurrentItem(item2, 0, QItemSelectionModel.Toggle) assert len(self.widget.layerTree.selectedItems()) == 2 return layer def test_or_combine(self): layer = self.setup_two_subset_selection() old_subsets = set(layer.subsets) self.widget._or_action.trigger() new_subsets = set(layer.subsets) diff = list(old_subsets ^ new_subsets) assert len(diff) == 1 assert isinstance(diff[0].subset_state, core.subset.OrState) def test_and_combine(self): layer = self.setup_two_subset_selection() old_subsets = set(layer.subsets) self.widget._and_action.trigger() new_subsets = set(layer.subsets) diff = list(old_subsets ^ new_subsets) assert len(diff) == 1 assert isinstance(diff[0].subset_state, core.subset.AndState) def test_invert(self): layer = self.add_layer_via_method() sub = layer.edit_subset item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) self.widget._invert_action.trigger() assert isinstance(sub.subset_state, core.subset.InvertState) def test_xor_combine(self): layer = self.setup_two_subset_selection() old_subsets = set(layer.subsets) self.widget._xor_action.trigger() new_subsets = set(layer.subsets) diff = list(old_subsets ^ new_subsets) assert len(diff) == 1 assert isinstance(diff[0].subset_state, core.subset.XorState) def test_actions_enabled_single_subset_selection(self): layer = self.add_layer_via_method() item = self.widget[layer.edit_subset] self.widget.layerTree.setCurrentItem(item) assert not self.widget._or_action.isEnabled() assert not self.widget._and_action.isEnabled() assert not self.widget._xor_action.isEnabled() assert self.widget._new_action.isEnabled() assert self.widget._copy_action.isEnabled() assert self.widget._duplicate_action.isEnabled() assert not self.widget._paste_action.isEnabled() assert self.widget._invert_action.isEnabled() assert self.widget._clear_action.isEnabled() def test_actions_enabled_single_data_selection(self): layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) assert not self.widget._or_action.isEnabled() assert not self.widget._and_action.isEnabled() assert not self.widget._xor_action.isEnabled() assert self.widget._new_action.isEnabled() assert not self.widget._copy_action.isEnabled() assert not self.widget._duplicate_action.isEnabled() assert not self.widget._paste_action.isEnabled() assert not self.widget._invert_action.isEnabled() assert not self.widget._clear_action.isEnabled() def test_actions_enabled_multi_subset_selection(self): layer = self.setup_two_subset_selection() assert self.widget._or_action.isEnabled() assert self.widget._and_action.isEnabled() assert self.widget._xor_action.isEnabled() assert not self.widget._new_action.isEnabled() assert not self.widget._copy_action.isEnabled() assert not self.widget._duplicate_action.isEnabled() assert not self.widget._paste_action.isEnabled() assert self.widget._invert_action.isEnabled() assert not self.widget._clear_action.isEnabled() def test_remove_all_layers(self): for d in self.collect: self.widget.add_layer(d) self.widget.remove_all_layers() for d in self.collect: assert not self.layer_present(d) def test_checkable_toggle(self): self.widget.set_checkable(True) assert self.widget.is_checkable() self.widget.set_checkable(False) assert not self.widget.is_checkable() def test_remove_layer_keeps_layer_in_collection(self): layer = self.add_layer_via_method() self.widget.remove_layer(layer) assert layer in self.widget.data_collection def test_remove_and_delete_removes_from_collection(self): layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item) self.widget.remove_and_delete_selected() assert not self.layer_present(layer) assert not layer in self.widget.data_collection def test_set_data_collection(self): layer = self.add_layer_via_method() dc = core.data_collection.DataCollection() self.widget.data_collection = dc assert self.widget.data_collection is dc assert not self.layer_present(layer) def test_edit_layer_label(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_label' with patch(pth) as edit_layer_label: layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 0) self.widget.edit_current_layer() edit_layer_label.assert_called_once_with(layer) def test_edit_layer_color(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_color' with patch(pth) as edit_layer_color: layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 1) self.widget.edit_current_layer() edit_layer_color.assert_called_once_with(layer) def test_edit_layer_symbol(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_symbol' with patch(pth) as edit_layer_symbol: layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 2) self.widget.edit_current_layer() edit_layer_symbol.assert_called_once_with(layer) def test_edit_layer_point_size(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.edit_layer_point_size' with patch(pth) as edit_layer_point_size: layer = self.add_layer_via_method() item = self.widget[layer] self.widget.layerTree.setCurrentItem(item, 3) self.widget.edit_current_layer() edit_layer_point_size.assert_called_once_with(layer) def test_add_data_creates_default_label(self): layer = self.data[0] layer.style.label = None self.widget.add_layer(layer) assert layer in self.widget assert layer.style.label == "Data 0" def test_load_data(self): pth = 'glue.qt.widgets.layer_tree_widget.qtutil.data_wizard' with patch(pth) as wizard: wizard.return_value = self.data[0] self.widget._load_data() assert self.layer_present(self.data[0]) def test_load_data_doesnt_double_add(self): """bugfix""" pth = 'glue.qt.widgets.layer_tree_widget.qtutil.data_wizard' with patch(pth) as wizard: wizard.return_value = self.data[0] assert self.widget.layerTree.topLevelItemCount() == 0 self.widget._load_data() assert self.widget.layerTree.topLevelItemCount() == 1 def test_sync_external_layer_ignored(self): assert not self.data[0] in self.widget self.widget.sync_layer(self.data[0]) def test_clear_subset(self): layer = self.add_layer_via_method() sub = layer.edit_subset item = self.widget[sub] self.widget.layerTree.setCurrentItem(item) dummy_state = MagicMock() sub.subset_state = dummy_state self.widget._clear_subset() assert not sub.subset_state == dummy_state def test_remove_message_global(self): """RemoveData messages should be processed, regardless of origin""" w = LayerTreeWidget() data = core.data.Data() hub = core.hub.Hub(w) dc = core.data_collection.DataCollection() w.add_layer(data) msg = core.message.DataCollectionDeleteMessage(dc, data) hub.broadcast(msg) assert data not in w
class SlaController(QApplication): def __init__(self, argv): QApplication.__init__(self, argv) # main window self.__mainWindow = QMainWindow() self.__ui1 = Ui_MainWindow() self.__glMain = object() self.__stl_model = StlModel() self.__stl_view = None # printing dialog self.__printingDialog = QDialog() self.__ui2 = Ui_PrintingDialog() # printing window self.__printingWindow = QMainWindow() self.__ui3 = Ui_PrintingWindow() self.__glStatus = object() # printer settings self.__printerSettings = QDialog() self.__ui4 = Ui_PrinterSettings() # slicing dialog # ToDo find something working as DropDown or get ComboBox working #self.__ui5 = ... # slicing window self.__glSlice = object() self.__slicingwindow = QMainWindow() self.__ui6 = Ui_SlicingWindow() self.__slicing_model = None self.__slicing_view = None self.__slices = None self.__slicing_index = 0 self.__connection = None self.__config = ConfigurationModel() self.current_z = 0 def start(self): self.initWindows() self.makeConnections() self.__mainWindow.show() sys.exit(self.exec_()) def initWindows(self): #self.connection.start() self.init_main() self.init_printer_settings() self.init_printing_window() self.init_printing_dialog() # self.init_slicing_dialog() self.init_slicing_window() def init_main(self): self.__glMain = GLWidget() self.__ui1.setupUi(self.__mainWindow) self.__ui1.OpenGlPanel.addWidget(self.__glMain) # self.installEventFilter(self.__glMain) def init_printing_dialog(self): ''' Initiating printer settings dialogue (individual options for each print) ''' self.__ui2.setupUi(self.__printingDialog) def init_printer_settings(self): ''' Initiating general printer settings window (for overarching printer settings that are always the same with the same printer) ''' self.__ui4.setupUi(self.__printerSettings) # initial settings load self.loadPrinterSettings() def init_printing_window(self): ''' Initiating printing window ''' #self.__glStatus = GLWidget() self.__ui3.setupUi(self.__printingWindow) #self.__ui3.OpenGlPanel.addWidget(self.__glMain) def init_slicing_window(self): ''' Initializing slicing window ''' self.__glSlice = GLWidget() self.__glSlice.allow_rot = False self.__glSlice.allow_zoom = True #self.__glSlice.draw_frame = True self.__ui6.setupUi(self.__slicingwindow) self.__ui6.OpenGlPanel.addWidget(self.__glSlice) def makeConnections(self): ''' make connections between signal and slots so that user interactions lead to according actions on the model or view ''' self.__ui1.importFileButton.clicked.connect(self.fileDialogFunction) self.__ui1.StartPrintButton.clicked.connect(self.__printingDialog.show) self.__ui1.printerSettingsButton.clicked.connect(self.__printerSettings.show) self.__ui1.CenterButton.clicked.connect(self.__glMain.reset) self.__ui1.MeshButton.clicked.connect(self.__glMain.mesh) self.__ui1.BoundingBoxButton.clicked.connect(self.__glMain.bounding_box) self.__ui1.showCutButton.clicked.connect(self.showcut) self.__ui2.CancelButton.clicked.connect(self.__printingDialog.close) self.__ui2.OkButton.clicked.connect(self.switchToPrintingMode) self.__ui1.SlicingButton.clicked.connect(self.__slicingwindow.show) self.__ui1.SlicingButton.clicked.connect(self.doSlicing) #ui1.DownPosButton.clicked.connect(MoveStepper, [False,2]) #why cant i call functions with parameters? #ui1.UpPosButton.clicked.connect(MoveStepper(True, N)) self.__ui4.OkButton.clicked.connect(self.savePrinterSettingsToFile) self.__ui4.CancelButton.clicked.connect(self.__printerSettings.close) self.__ui6.nextButton.clicked.connect(self.next_slice) self.__ui6.prevButton.clicked.connect(self.prev_slice) def switchToPrintingMode(self): self.__ui1.OpenGlPanel.removeWidget(self.__glMain) self.__mainWindow.close() self.__printerSettings.close() #shouldnt be open at this point, but you never know self.__printingDialog.close() self.__ui3.OpenGlPanel.addWidget(self.__glMain) self.__printingWindow.show() self.sendToRaspberry() def savePrinterSettingsToFile(self): # update values in config file self.__config.width = float(self.__ui4.AreaWidth.text()) self.__config.length = float(self.__ui4.AreaLength.text()) self.__config.height = float(self.__ui4.AreaHeight.text()) self.__config.height_per_rev = float(self.__ui4.HeightPerRevolution.text()) self.__config.steps_per_rev = float(self.__ui4.StepsPerRevolution.text()) self.__config.server_ip = str(self.__ui4.ipAdress.text()) #self.__config.ssl() self.__config.illumination_time = float(self.__ui4.illuminationTime.text()) self.__config.illumination_intentsity = float(self.__ui4.illuminationIntensity.text()) self.__config.liquid_price = float(self.__ui4.PrinterLiquidPrice.text()) # save config to standard path self.__config.save() #close the window self.__printerSettings.close() def loadPrinterSettings(self): #ToDo: Implement this with a XML file configfile = open('PrinterSettings.conf', 'r') settings=json.load(configfile) # parse file to configuration object self.__config.parse(settings) self.__ui4.AreaWidth.clear() self.__ui4.AreaWidth.insert('%.2f' % self.__config.width) self.__ui4.AreaLength.clear() self.__ui4.AreaLength.insert('%.2f' % self.__config.length) self.__ui4.AreaHeight.clear() self.__ui4.AreaHeight.insert('%.2f' % self.__config.height) self.__ui4.HeightPerRevolution.clear() self.__ui4.HeightPerRevolution.insert('%.2f' % self.__config.height_per_rev) self.__ui4.StepsPerRevolution.clear() self.__ui4.StepsPerRevolution.insert('%.2f' % self.__config.steps_per_rev) self.__ui4.ipAdress.clear() self.__ui4.ipAdress.insert(self.__config.server_ip) self.__ui4.illuminationTime.clear() self.__ui4.illuminationTime.insert('%.2f' % self.__config.illumination_time) self.__ui4.illuminationIntensity.clear() self.__ui4.illuminationIntensity.insert('%.2f' % self.__config.illumination_intentsity) self.__ui4.PrinterLiquidPrice.clear() self.__ui4.PrinterLiquidPrice.insert('%.2f' % self.__config.liquid_price) configfile.close() def MoveStepper(up=True, no_of_steps=1): #This is going to be the motor step function print up print no_of_steps def MoveStepperToEndPos(self,Endposition=True): #False is Startposition pass def ManualPrintingAbort(self): w = QWidget() QMessageBox.critical(w, 'Message', 'Printing stopped by user!') self.MoveStepperToEndPos(True) self.__printingWindow.close() self.__mainWindow.show() def fileDialogFunction(self): filename = QFileDialog.getOpenFileName(self.__mainWindow, 'Open File') #LINUX #filename = QFileDialog.getOpenFileName(mainWindow, 'Open File', 'C:\') #WINDOWS print("") print("filepath: " + str(filename)) if filename.contains(".stl"): self.__stl_model.open(filename) if not self.__stl_view is None: self.__glMain.delDrawable(self.__stl_view) self.__stl_view = StlModelView(self.__stl_model) scale = self.__stl_view.scale self.__glMain.reset() if scale > -1: self.__glMain.scale = scale print("new scale:" + str(scale)) else: print("no new scale") self.__glMain.addDrawable(self.__stl_view) self.__slicing_model = None self.__slices = None def sendToRaspberry(self): configfile = open('PrinterSettings.conf', 'r') # SettingsList=json.load(configfile) # configfile.close() # # sentFile = {'file': ('../View/PrinterSettings.conf', open('../View/PrinterSettings.conf', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})} # r1 = requests.post(str(SettingsList[11]) + ":/home/pi/printerData", files=sentFile) # r2 = requests.post(str(SettingsList[11]) + ":/home/pi/printerData", data=str(SettingsList)) # # # #Explaining what each button on the PrintingDialog does # self.__ui2.OkButton.clicked.connect(self.switchToPrintingMode) # self.__ui2.CancelButton.clicked.connect(self.__printingDialog.close) # # #Explaining what each button on the PrintingWindow does # self.__ui3.StopPrintButton.clicked.connect(self.ManualPrintingAbort) # # #Explaining what each button on the printingSettingsWindow does # if os.path.isfile('PrinterSettings.conf'): # self.loadPrinterSettings() # # self.__ui4.CancelButton.clicked.connect(self.__printerSettings.close) # self.__ui4.OkButton.clicked.connect(self.savePrinterSettingsToFile) def doSlicing(self): # only slice if new model has been loaded if self.__slices is None and self.__slicing_model is None: self.__slicing_model = EquiSlicer(self.__stl_model) self.__slices = self.__slicing_model.slice(100) slice = self.__slices[self.__slicing_index] scale = self.__slicing_model.scale self.__glSlice.update_scale(scale) #print(slice) n = len(self.__slices) s = "Equidistanc slicer used n= " + str(n) + " slices have been created \n currently displaying slice [" s = s + str(self.__slicing_index+1) + "] \n " self.__ui6.algorithmLabel.setText(s) self.__slicing_view = SliceModelView(slice) self.__glSlice.addDrawable(self.__slicing_view) def next_slice(self): i = self.__slicing_index n = len(self.__slices) if i+1 <n: self.update_slice(i+1) def prev_slice(self): i = self.__slicing_index if i-1 >= 0: self.update_slice(i-1) def update_slice(self,i): slice = self.__slices[i] self.__slicing_index = i n = len(self.__slices) s = "Equidistanc slicer used n= " + str(n) + " slices have been created \n currently displaying slice [" s = s + str(self.__slicing_index+1) + "] \n " #print("") #print("################################") #print("") #print(slice) #print("") #print("") #print("") self.__glSlice.delDrawable(self.__slicing_view) self.__ui6.algorithmLabel.setText(s) self.__slicing_view = SliceModelView(slice) self.__glSlice.addDrawable(self.__slicing_view) self.__glSlice.update() def showcut(self): x0, x1 = self.__stl_model.xlims y0, y1 = self.__stl_model.ylims dimx = x1-x0 dimy = y1-y0 self.current_z = float(self.__ui1.cutZCoordinate.text()) self.__glMain.addDrawable(PlaneCutView(z=self.current_z, dimx=2*dimx, dimy=2*dimy, stl_model=self.__stl_model))
class TestScatterWidget(object): def setup_method(self, method): self.hub = core.hub.Hub() self.data = example_data.test_data() self.collect = core.data_collection.DataCollection(list(self.data)) self.widget = ScatterWidget(self.collect) self.win = QMainWindow() self.win.setCentralWidget(self.widget) self.connect_to_hub() self.win.show() def teardown_method(self, method): self.win.close() def connect_to_hub(self): self.widget.register_to_hub(self.hub) self.collect.register_to_hub(self.hub) def add_layer_via_hub(self): layer = self.data[0] layer.label = 'Test Layer' self.collect.append(layer) return layer def add_layer_via_method(self, index=0): layer = self.data[index] self.widget.add_data(layer) return layer def plot_data(self, layer): """ Return the data bounds for a given layer (data or subset) Output format: [xmin, xmax], [ymin, ymax] """ client = self.widget.client x, y = client.artists[layer][0].get_data() xmin = x.min() xmax = x.max() ymin = y.min() ymax = y.max() return [xmin, xmax], [ymin, ymax] def plot_limits(self): """ Return the plot limits Output format [xmin, xmax], [ymin, ymax] """ ax = self.widget.client.ax xlim = ax.get_xlim() ylim = ax.get_ylim() return xlim, ylim return def assert_layer_inside_limits(self, layer): """Assert that points of a layer are within plot limits """ xydata = self.plot_data(layer) xylimits = self.plot_limits() assert xydata[0][0] >= xylimits[0][0] assert xydata[1][0] >= xylimits[1][0] assert xydata[0][1] <= xylimits[0][1] assert xydata[1][1] <= xylimits[1][1] def is_layer_present(self, layer): return self.widget.client.is_layer_present(layer) def is_layer_visible(self, layer): return self.widget.client.is_visible(layer) def test_rescaled_on_init(self): layer = self.add_layer_via_method() self.assert_layer_inside_limits(layer) def test_hub_data_add_is_ignored(self): layer = self.add_layer_via_hub() assert not self.widget.client.is_layer_present(layer) def test_valid_add_data_via_method(self): layer = self.add_layer_via_method() assert self.is_layer_present(layer) def test_add_first_data_updates_combos(self): layer = self.add_layer_via_method() xatt = str(self.widget.ui.xAxisComboBox.currentText()) yatt = str(self.widget.ui.yAxisComboBox.currentText()) assert xatt is not None assert yatt is not None def test_flip_x(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.xFlipCheckBox, Qt.LeftButton) assert self.widget.client.is_xflip() QTest.mouseClick(self.widget.ui.xFlipCheckBox, Qt.LeftButton) assert not self.widget.client.is_xflip() def test_flip_y(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.yFlipCheckBox, Qt.LeftButton) assert self.widget.client.is_yflip() QTest.mouseClick(self.widget.ui.yFlipCheckBox, Qt.LeftButton) assert not self.widget.client.is_yflip() def test_log_x(self): layer = self.add_layer_via_method() QTest.mouseClick(self.widget.ui.xLogCheckBox, Qt.LeftButton) assert self.widget.client.is_xlog() QTest.mouseClick(self.widget.ui.xLogCheckBox, Qt.LeftButton) assert not self.widget.client.is_xlog() def test_log_y(self): QTest.mouseClick(self.widget.ui.yLogCheckBox, Qt.LeftButton) assert self.widget.client.is_ylog() QTest.mouseClick(self.widget.ui.yLogCheckBox, Qt.LeftButton) assert not self.widget.client.is_ylog() def test_double_add_ignored(self): layer = self.add_layer_via_method() nobj = self.widget.ui.xAxisComboBox.count() layer = self.add_layer_via_method() assert self.widget.ui.xAxisComboBox.count() == nobj def test_subsets_dont_duplicate_fields(self): layer = self.add_layer_via_method() nobj = self.widget.ui.xAxisComboBox.count() subset = layer.new_subset() subset.register() assert self.widget.ui.xAxisComboBox.count() == nobj def test_correct_title_single_data(self): ct = self.widget.client.layer_count assert ct == 0 layer = self.add_layer_via_method() ct = self.widget.client.layer_count assert ct == 1 assert len(layer.label) > 0 assert self.widget.windowTitle() == layer.label def test_title_updates_with_label_change(self): layer = self.add_layer_via_method() assert layer.hub is self.hub layer.label = "changed label" assert self.widget.windowTitle() == layer.label def test_title_updates_with_second_data(self): l1 = self.add_layer_via_method(0) l2 = self.add_layer_via_method(1) expected = '%s | %s' % (l1.label, l2.label) self.widget.windowTitle() == expected
class UiController: def __init__(self, controller, debug_mode, logger): self.controller = controller self.datahandler = controller.datahandler self.debug_mode = debug_mode self.logger = logger ### Main Window self.main_widget = QMainWindow() self.main_widget.setAttribute(Qt.WA_Maemo5StackedWindow) self.main_ui = Ui_DropN900Widget() self.main_ui.setupUi(self.main_widget) # Stacked layout for context switching self.stacked_layout = QtGui.QStackedLayout() self.main_ui.centralwidget.setLayout(self.stacked_layout) # Menu items self.action_transfers = QtGui.QAction("Transfers", self.main_widget) self.action_settings = QtGui.QAction("Settings", self.main_widget) self.action_sync = QtGui.QAction("Synchronize", self.main_widget) self.action_sync_photos = QtGui.QAction("Sync Media", self.main_widget) self.action_console = QtGui.QAction("Show Log", self.main_widget) self.action_about = QtGui.QAction("About", self.main_widget) self.action_exit = QtGui.QAction("Exit", self.main_widget) self.main_ui.menubar.addAction(self.action_transfers) self.main_ui.menubar.addAction(self.action_settings) self.main_ui.menubar.addAction(self.action_sync) self.main_ui.menubar.addAction(self.action_sync_photos) self.main_ui.menubar.addAction(self.action_console) self.main_ui.menubar.addAction(self.action_about) self.main_ui.menubar.addAction(self.action_exit) # Connects self.action_transfers.triggered.connect(self.show_transfer_widget) self.action_sync.triggered.connect(self.synchronize_now) self.action_sync_photos.triggered.connect(self.synchronize_now_photos) self.action_settings.triggered.connect(self.show_settings_widget) self.action_console.triggered.connect(self.show_console) self.action_about.triggered.connect(self.show_about) self.action_exit.triggered.connect(self.shut_down) ### Trusted Login Widget self.trusted_login_widget = QWidget() self.trusted_login_ui = Ui_TrustedLoginWidget() self.trusted_login_ui.setupUi(self.trusted_login_widget) self.trusted_login_ui.label_icon.setPixmap(QPixmap(self.datahandler.datapath("ui/images/dropn900_logo.png")).scaled(65,65)) # Connects self.trusted_login_ui.button_auth.clicked.connect(self.try_trusted_login) ### Manager Widget self.manager_widget = QWidget() self.manager_ui = Ui_ManagerWidget() self.manager_ui.setupUi(self.manager_widget) # Tree Controller tree = self.manager_ui.tree_widget self.tree_controller = TreeController(tree, self.manager_ui, self.controller, self.logger) # Hide public link elements on start self.manager_ui.button_copy_public_link.hide() self.manager_ui.button_open_public_link.hide() # Connects self.manager_ui.button_copy_public_link.clicked.connect(self.copy_item_link) self.manager_ui.button_open_public_link.clicked.connect(self.open_item_link) self.manager_ui.button_download.clicked.connect(self.item_download) self.manager_ui.button_upload.clicked.connect(self.item_upload) self.manager_ui.button_rename.clicked.connect(self.item_rename) self.manager_ui.button_remove.clicked.connect(self.item_remove) self.manager_ui.button_new_folder.clicked.connect(self.item_new_folder) self.manager_ui.sync_button.clicked.connect(self.synchronize_now) self.last_dl_location = None self.last_ul_location = None ### Console widget self.console_widget = QWidget(self.main_widget, Qt.Window) self.console_widget.setAttribute(Qt.WA_Maemo5StackedWindow) self.console_ui = Ui_ConsoleWidget() self.console_ui.setupUi(self.console_widget) self.console_ui.button_save.clicked.connect(self.save_log_to_file) self.console_ui.button_back.clicked.connect(self.hide_console) ### Settings widget self.settings_widget = None ### Fill stacked layout self.stacked_layout.addWidget(self.trusted_login_widget) self.stacked_layout.addWidget(self.manager_widget) self.stacked_layout.setCurrentWidget(self.trusted_login_widget) ### Loading Widget self.loading_widget = QWidget(self.manager_widget) self.loading_ui = Ui_LoadingWidget() self.loading_ui.setupUi(self.loading_widget) self.manager_ui.action_layout.insertWidget(3, self.loading_widget) self.loading_widget.hide() self.tree_controller.set_loading_ui(self.loading_ui) # Init loading animation self.loading_animation = QMovie(self.datahandler.datapath("ui/images/loading.gif"), "GIF", self.loading_ui.load_animation_label) self.loading_animation.setCacheMode(QMovie.CacheAll) self.loading_animation.setSpeed(150) self.loading_animation.setScaledSize(QtCore.QSize(48,48)) self.loading_ui.load_animation_label.setMovie(self.loading_animation) # Init hide timer and icons for information messages self.information_message_timer = QTimer() self.information_message_timer.setSingleShot(True) self.information_message_timer.timeout.connect(self.hide_information_message) self.information_icon_ok = QPixmap(self.datahandler.datapath("ui/icons/check.png")).scaled(24,24) self.information_icon_error = QPixmap(self.datahandler.datapath("ui/icons/cancel.png")).scaled(24,24) self.information_icon_queue = QPixmap(self.datahandler.datapath("ui/icons/queue.png")).scaled(24,24) ### About dialog self.about_dialog = AboutDialog(self) self.set_synching(False) def set_synching(self, syncing): self.manager_ui.sync_button.setVisible(not syncing) self.manager_ui.sync_label.setVisible(syncing) def set_settings_widget(self, settings_widget): self.settings_widget = settings_widget def set_transfer_widget(self, transfer_widget): self.transfer_widget = transfer_widget def synchronize_now(self): self.settings_widget.sync_now_clicked() def synchronize_now_photos(self): self.controller.sync_manager.sync_media() def show(self): # Nokia N900 screen resolution, full screen self.main_widget.resize(800, 480) self.main_widget.show() self.main_widget.showMaximized() def show_settings_widget(self): if self.settings_widget != None: if not self.settings_widget.isVisible(): self.settings_widget.show() self.settings_widget.check_settings() def show_transfer_widget(self): if self.settings_widget.isVisible(): self.settings_widget.hide() self.transfer_widget.show() def show_about(self): if not self.about_dialog.isVisible(): self.about_dialog.show() def show_note(self, message): QMaemo5InformationBox.information(None, QString(message), 0) def show_banner(self, message, timeout = 5000): QMaemo5InformationBox.information(None, QString(message), timeout) def show_loading_ui(self, message = "", loading = True): self.loading_ui.info_label.setText(message) self.loading_ui.info_label_icon.hide() self.thumb_was_visible = self.manager_ui.thumb_container.isVisible() self.manager_ui.thumb_container.hide() self.loading_widget.show() self.loading_ui.load_animation_label.setVisible(loading) if loading: self.loading_animation.start() else: self.loading_animation.stop() def show_information_ui(self, message, succesfull, timeout = 4000): self.loading_ui.load_animation_label.hide() self.thumb_was_visible = self.manager_ui.thumb_container.isVisible() if self.thumb_was_visible: self.manager_ui.thumb_container.hide() self.loading_ui.info_label.setText(message) if succesfull == None: icon = self.information_icon_queue elif succesfull: icon = self.information_icon_ok else: icon = self.information_icon_error self.loading_ui.info_label_icon.setPixmap(icon) self.loading_ui.info_label_icon.show() self.loading_widget.show() self.information_message_timer.start(timeout) def hide_loading_ui(self): if not self.information_message_timer.isActive(): self.loading_widget.hide() if self.loading_animation.state() == QMovie.Running: self.loading_animation.stop() def hide_information_message(self): self.loading_ui.info_label_icon.hide() self.hide_loading_ui() self.manager_ui.thumb_container.setVisible(self.thumb_was_visible) def try_trusted_login(self): self.trusted_login_ui.label_error.setText("") email = self.trusted_login_ui.line_edit_email.text() password = self.trusted_login_ui.line_edit_password.text() error = None if email.isEmpty(): error = "Email can't be empty!" elif email.count("@") != 1: error = "Invalid email, check your @ signs!" elif email.contains(" "): error = "Invalid email, can't have spaces!" elif password.isEmpty(): error = "Password can't be empty!" if error == None: self.show_banner("Authenticating...", 3000) self.set_trusted_login_info("Authenticating, please wait...") self.truested_email = self.datahandler.to_unicode(str(email.toUtf8())) self.trusted_password = self.datahandler.to_unicode(str(password.toUtf8())) QTimer.singleShot(100, self.do_trusted_login_networking) else: self.set_trusted_login_error(error) def set_trusted_login_error(self, error): self.trusted_login_ui.label_error.setStyleSheet("color: #9d1414;") self.trusted_login_ui.label_error.setText(error) self.truested_email = None self.trusted_password = None def set_trusted_login_info(self, info): self.trusted_login_ui.label_error.setStyleSheet("color: #149d2b;") self.trusted_login_ui.label_error.setText(info) def do_trusted_login_networking(self): self.controller.end_trusted_auth(self.truested_email.encode("utf-8"), self.trusted_password.encode("utf-8")) self.truested_email = None self.trusted_password = None def reset_trusted_login(self): self.trusted_login_ui.line_edit_email.clear() self.trusted_login_ui.line_edit_password.clear() self.trusted_login_ui.label_error.clear() def switch_context(self, view = None): widget = None if view == "trustedlogin": widget = self.trusted_login_widget if view == "manager": widget = self.manager_widget if view == "console": self.console_widget.show() if view == None and self.last_view != None: widget = self.last_view if widget != None: self.last_view = self.stacked_layout.currentWidget() self.stacked_layout.setCurrentWidget(widget) def get_selected_data(self): return self.tree_controller.selected_data # Signal handlers def shut_down(self): self.main_widget.close() def show_console(self): if self.console_widget.isVisible() == False: self.switch_context("console") else: self.hide_console() def hide_console(self): self.console_widget.hide() def save_log_to_file(self): filename = self.datahandler.get_data_dir_path() + "dropn900.log" log_string = str(self.console_ui.text_area.toPlainText()) try: log_file = open(filename, "w") log_file.write(log_string) log_file.close() self.show_banner("Log saved to " + filename) except IOError: self.logger.error("Could not open " + filename + " to save log") def browser_control_clicked(self): if self.controller.connected: self.switch_context() else: self.controller.end_auth() def copy_item_link(self): url = self.tree_controller.current_public_link if url == None: return self.datahandler.copy_url_to_clipboard(url) def open_item_link(self): url = self.tree_controller.current_public_link if url == None: return QDesktopServices.openUrl(QtCore.QUrl(url)) def item_download(self): data = self.get_selected_data() if data == None: return if self.datahandler.dont_show_dl_dialog == False: # This dialog shows sometimes strange stuff on maemo5 # It's a PyQt4 bug and its the best we got, you can cope with this if self.last_dl_location == None: self.last_dl_location = self.datahandler.get_data_dir_path() local_folder_path = QFileDialog.getExistingDirectory(self.manager_widget, QString("Select Download Folder"), QString(self.last_dl_location), QFileDialog.ShowDirsOnly|QFileDialog.HideNameFilterDetails|QFileDialog.ReadOnly) if local_folder_path.isEmpty(): return py_unicode_path = self.datahandler.to_unicode(str(local_folder_path.toUtf8())) self.last_dl_location = py_unicode_path store_path = py_unicode_path + "/" + data.name else: dir_check = QDir(self.datahandler.get_data_dir_path()) if not dir_check.exists(): self.show_note("Cannot download, destination " + self.datahandler.get_data_dir_path() + " does not exist. Please set a new folder in settings.") return store_path = self.datahandler.get_data_dir_path() + data.name self.controller.connection.get_file(data.path, data.root, store_path, data.get_size(), data.mime_type) def item_upload(self): data = self.get_selected_data() if data == None or not data.is_folder(): return # This dialog shows sometimes strange stuff on maemo5 # It's a PyQt4 bug and its the best we got, you can cope with this if self.last_ul_location == None: self.last_ul_location = self.datahandler.get_data_dir_path() local_file_path = QFileDialog.getOpenFileName(self.manager_widget, QString("Select File for Upload"), QString(self.last_ul_location)) if local_file_path.isEmpty(): return py_unicode_path = self.datahandler.to_unicode(str(local_file_path.toUtf8())) self.last_ul_location = py_unicode_path[0:py_unicode_path.rfind("/")] self.controller.connection.upload_file(data.path, data.root, py_unicode_path) def item_rename(self): data = self.get_selected_data() if data == None: return # Get new name from user old_name = data.get_name() keyword = "file" if not data.is_folder() else "folder" new_name, ok = QInputDialog.getText(None, "Renaming " + keyword, "Give new name for " + keyword + " " + old_name, QtGui.QLineEdit.Normal, old_name) if not ok: return # Validate with QString if not self.is_name_valid(new_name, keyword): return # Make QString to python 'unicode' new_name = self.datahandler.to_unicode(str(new_name.toUtf8())) if old_name == new_name: return # Extension will be lost, ask user if he wants to leave it q_old_name = QtCore.QString(old_name) if q_old_name.contains("."): if not new_name.contains("."): format = old_name[q_old_name.lastIndexOf("."):] confirmation = QMessageBox.question(None, "Extension missing", "Do you want to append the original '" + format + "' extensions to the filename '" + new_name + "'?", QMessageBox.Yes, QMessageBox.No) if confirmation == QMessageBox.Yes: new_name.append(format) # Get final new path and rename if data.parent == "/": new_name = data.parent + new_name else: new_name = data.parent + "/" + new_name self.controller.connection.rename(data.root, data.path, new_name, data) def item_remove(self): data = self.get_selected_data() if data == None: return if data.is_folder(): confirmation = QMessageBox.question(None, "Remove folder verification", "Are you sure you want to remove the entire folder " + data.get_name() +"?", QMessageBox.Yes, QMessageBox.Cancel) else: confirmation = QMessageBox.question(None, "Remove file verification", "Are you sure you want to remove " + data.get_name() +"?", QMessageBox.Yes, QMessageBox.Cancel) if confirmation == QMessageBox.Yes: self.controller.connection.remove_file(data.root, data.path, data.parent, data.is_folder()) def item_new_folder(self): data = self.get_selected_data() if data == None: return if not data.is_folder(): return full_create_path = data.path + "/" new_folder_name, ok = QInputDialog.getText(None, "Give new folder name", "") if not ok: return # Validate QString if not self.is_name_valid(new_folder_name, "folder"): return # Make QString to python unicode new_folder_name = self.datahandler.to_unicode(str(new_folder_name.toUtf8())) full_create_path = data.path + "/" + new_folder_name self.controller.connection.create_folder(data.root, full_create_path, new_folder_name, data.path) def is_name_valid(self, name, item_type): if name.isEmpty() or name.isNull(): return False if name.contains("/"): self.show_information_ui("Cant use / in new " + item_type + " name", False) return False if name.contains("\\"): self.show_information_ui("Cant use \ in new " + item_type + " name", False) return False if name.startsWith(" "): self.show_information_ui("New " + item_type + " name cant start with a space", False) return False if name.endsWith(" "): self.show_information_ui("New " + item_type + " name cant end with a space", False) return False return True
class adminPanel: def __init__(self, parent=None): self.MainWindow = QMainWindow() if Login().exec_() == QDialog.Accepted: self.panel() def panel(self): modulo_logger.debug('Creando panel de admin...') self.ui = Ui_MainWindow() self.ui.setupUi(self.MainWindow) self.ui.labelErrorPermitidos.setVisible(False) self.ui.labelErrorDenegados.setVisible(False) self.ui.botonCancelar.clicked.connect(self.salir) self.ui.pushButtonPermitir.clicked.connect(self.agregarPermitido) self.ui.pushButtonDenegar.clicked.connect(self.agregarDenegado) self.ui.botonEliminarPermitido.clicked.connect(self.eliminarPermitido) self.ui.botonEliminarDenegado.clicked.connect(self.eliminarDenegado) self.ui.botonGuardar.clicked.connect(self.refrezcarDominios) modulo_logger.debug('Utilizando la db: %s' % config.PATH_DB) self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE') self.db.setDatabaseName(config.PATH_DB) self.db.open() # Listo los dominios denegados self.modelPermitidos = QtSql.QSqlTableModel(None, self.db) modulo_logger.debug('Listando dominios permitidos') self.modelPermitidos.setTable("dominios_usuario") # requiere de un submit para que se apliquen los cambios self.modelPermitidos.setEditStrategy(2) self.modelPermitidos.setFilter('estado=1') self.modelPermitidos.select() self.modelPermitidos.setHeaderData(0, 1, "Dominios permitidos") self.ui.tableViewPermitidos.setModel(self.modelPermitidos) self.ui.tableViewPermitidos.hideColumn(1) self.ui.tableViewPermitidos.hideColumn(2) self.ui.tableViewPermitidos.resizeRowsToContents() self.ui.tableViewPermitidos.show() # Listo los dominios denegados modulo_logger.debug('Listando dominios denegados') self.modelDenegados = QtSql.QSqlTableModel(None, self.db) self.modelDenegados.setTable("dominios_usuario") # requiere de un submit para que se apliquen los cambios self.modelDenegados.setEditStrategy(2) self.modelDenegados.setFilter('estado=2') self.modelDenegados.select() self.modelDenegados.setHeaderData(0, 1, "Dominios permitidos") self.ui.tableViewDenegados.setModel(self.modelDenegados) self.ui.tableViewDenegados.hideColumn(1) self.ui.tableViewDenegados.hideColumn(2) self.ui.tableViewDenegados.resizeRowsToContents() self.ui.tableViewDenegados.show() self.MainWindow.show() modulo_logger.debug('Fin de la creacion del panel de admin...') def salir(self): self.db.close() self.MainWindow.close() def guardar(self): modulo_logger.debug('Guardando dominios') self.modelPermitidos.submitAll() self.modelDenegados.submitAll() def verificarDominio(self, dominio): modulo_logger.debug('Verificando dominio: %s' % dominio) domvalido = re.match( '^(?:[a-zA-Z0-9]+(?:\-*[a-zA-Z0-9])*\.)+[a-zA-Z]{2,6}$', dominio ) modulo_logger.debug('Dominio %s - valido: %s' % (dominio, domvalido)) return domvalido def eliminarPermitido(self): modulo_logger.debug('Eliminando dominios permitidos seleccionados') rows = self.ui.tableViewPermitidos.selectedIndexes() for row in rows: self.ui.tableViewPermitidos.model().removeRow(row.row()) self.modelPermitidos.submitAll() def eliminarDenegado(self): modulo_logger.debug('Eliminando dominios denegados seleccionados') rows = self.ui.tableViewDenegados.selectedIndexes() for row in rows: self.ui.tableViewDenegados.model().removeRow(row.row()) self.modelDenegados.submitAll() def refrezcarDominios(self): modulo_logger.debug('Recargando dominios permitidos/denegados') url = 'http://%s:%s/!RecargarDominiosKerberus!' % (config.BIND_ADDRESS, config.BIND_PORT) con = httplib.HTTPConnection(config.BIND_ADDRESS, config.BIND_PORT) con.request(method='KERBERUSREFRESH', url=url) def agregarPermitido(self): self.ui.labelErrorPermitidos.setVisible(False) dominio = self.ui.lineEditPermitidos.text() modulo_logger.debug('Agregando dominio permitido: %s' % dominio) valido = self.verificarDominio(dominio) if valido: modulo_logger.debug('Agregando a la db el dominio permitido: %s' % dominio) consulta = QtSql.QSqlQuery() consulta.prepare("Insert into dominios_usuario (url,usuario,estado)" "values (:url, :usuario, :estado)") consulta.bindValue(":url", dominio) consulta.bindValue(":usuario", 2) consulta.bindValue(":estado", 1) consulta.exec_() self.modelPermitidos.submitAll() else: self.ui.labelErrorPermitidos.setVisible(True) def agregarDenegado(self): self.ui.labelErrorDenegados.setVisible(False) dominio = self.ui.lineEditDenegados.text() modulo_logger.debug('Agregando dominio denegado: %s' % dominio) valido = self.verificarDominio(dominio) if valido: modulo_logger.debug('Agregando a la db el dominio denegado: %s' % dominio) consulta = QtSql.QSqlQuery() consulta.prepare("Insert into dominios_usuario (url,usuario,estado)" "values (:url, :usuario, :estado)") consulta.bindValue(":url", dominio) consulta.bindValue(":usuario", 2) consulta.bindValue(":estado", 2) consulta.exec_() self.modelDenegados.submitAll() else: self.ui.labelErrorDenegados.setVisible(True)