class TrackProgressDialog(QDialog): finished = pyqtSignal() def __init__(self, parent=None, numStages=1): QDialog.__init__(self, parent) self.currentStep = 0 self.progress = None l = QVBoxLayout() self.setLayout(l) self.overallProgress = QProgressBar() self.overallProgress.setRange(0, numStages) self.overallProgress.setFormat("step %v of " + str(numStages)) self.currentStepProgress = QProgressBar() self.currentStepProgress.setRange(0, 100) self.currentStepProgress.setFormat("%p %") self.overallLabel = QLabel("Overall progress") self.currentStepLabel = QLabel("Current step") l.addWidget(self.overallLabel) l.addWidget(self.overallProgress) l.addWidget(self.currentStepLabel) l.addWidget(self.currentStepProgress) l.maximumSize() self.update() def __onNewStep(self, description): self.currentStep += 1 self.currentStepProgress.setValue(0) self.overallProgress.setValue(self.currentStep) self.currentStepLabel.setText(description) self.update() def __onCurrentStepProgressChanged(self, progress): timesHundred = round(1000.0 * progress) timesTen = round(100.0 * progress) if (not self.currentStepProgress.value() == timesTen) and (timesHundred - 10 * timesTen) == 0: self.currentStepProgress.setValue(timesTen) self.update() def run(self): self.trackProgress = TrackProgress(self) self.trackProgress.progress.connect( self.__onCurrentStepProgressChanged, Qt.BlockingQueuedConnection) self.trackProgress.newStep.connect(self.__onNewStep, Qt.BlockingQueuedConnection) self.trackProgress.done.connect(self.onTrackDone) self.trackProgress.start() def onTrackDone(self): self.trackProgress.wait( ) # Join the extractor thread so its safe to immediately destroy the window self.finished.emit() self.close()
class ProgressWidget(QgsMessageBar): def __init__(self, min, max, message, parent=None, timeout = 1.5): """ Constructs a progress widget """ super(self.__class__, self).__init__(parent) self.min = min self.max = max sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) if parent: self.setMinimumSize(parent.width(),40) else: self.setMinimumSize(766,40) self.setSizePolicy(sizePolicy) self.progressBar = QProgressBar() self.progressBar.setMinimum(min) self.progressBar.setMaximum(max) self.msgBarItem = QgsMessageBarItem(self.tr("INFO: "), message, self.progressBar, level=QgsMessageBar.INFO, duration=timeout) self.pushWidget(self.msgBarItem) def initBar(self): """ Initializes the progress bar """ self.progressBar.setValue(0) def step(self): """ Increments the progress bar """ value = self.progressBar.value() + 1 self.progressBar.setValue(value) if value == self.max: time.sleep(1) self.close()
class TestWindow(QWidget): def __init__(self): super(TestWindow, self).__init__() self.setWindowTitle("LivePlot Example Runner") layout = QHBoxLayout(self) button_layout = QVBoxLayout() time_layout = QHBoxLayout() time_spin = QSpinBox() self.timer = QTimer() time_spin.valueChanged.connect(self.timer.setInterval) self.timer.timeout.connect(self.iterate) self.progress_bar = QProgressBar() time_spin.setValue(50) time_spin.setRange(0, 1000) time_layout.addWidget(QLabel("Sleep Time (ms)")) time_layout.addWidget(time_spin) button_layout.addLayout(time_layout) tests = { 'plot y': test_plot_y, 'plot xy': test_plot_xy, 'plot parametric': test_plot_xy_parametric, 'plot z': test_plot_z, 'plot huge': test_plot_huge, 'append y': test_append_y, 'append xy': test_append_xy, 'append z': test_append_z, } fn_text_widget = QPlainTextEdit() fn_text_widget.setMinimumWidth(500) def make_set_iterator(iter): def set_iterator(): fn_text_widget.setPlainText(inspect.getsource(iter)) QApplication.instance().processEvents() self.iterator = iter() self.timer.start() return set_iterator for name, iter in tests.items(): button = QPushButton(name) button.clicked.connect(make_set_iterator(iter)) button_layout.addWidget(button) layout.addLayout(button_layout) text_layout = QVBoxLayout() text_layout.addWidget(fn_text_widget) text_layout.addWidget(self.progress_bar) layout.addLayout(text_layout) def iterate(self): try: self.iterator.next() self.progress_bar.setValue(self.progress_bar.value() + 1) except StopIteration: self.timer.stop() self.progress_bar.setValue(0)
class TestWindow(QWidget): def __init__(self): super(TestWindow, self).__init__() self.setWindowTitle("LivePlot Example Runner") layout = QHBoxLayout(self) button_layout = QVBoxLayout() time_layout = QHBoxLayout() time_spin = QSpinBox() self.timer = QTimer() time_spin.valueChanged.connect(self.timer.setInterval) self.timer.timeout.connect(self.iterate) self.progress_bar = QProgressBar() time_spin.setValue(50) time_spin.setRange(0, 1000) time_layout.addWidget(QLabel("Sleep Time (ms)")) time_layout.addWidget(time_spin) button_layout.addLayout(time_layout) tests = { 'plot y': test_plot_y, 'plot xy': test_plot_xy, 'plot parametric': test_plot_xy_parametric, 'plot z': test_plot_z, 'plot huge': test_plot_huge, 'append y': test_append_y, 'append xy': test_append_xy, 'append z': test_append_z, 'label': test_label, } fn_text_widget = QPlainTextEdit() fn_text_widget.setMinimumWidth(500) def make_set_iterator(iter): def set_iterator(): fn_text_widget.setPlainText(inspect.getsource(iter)) QApplication.instance().processEvents() self.iterator = iter() self.timer.start() return set_iterator for name, iter in tests.items(): button = QPushButton(name) button.clicked.connect(make_set_iterator(iter)) button_layout.addWidget(button) layout.addLayout(button_layout) text_layout = QVBoxLayout() text_layout.addWidget(fn_text_widget) text_layout.addWidget(self.progress_bar) layout.addLayout(text_layout) def iterate(self): try: self.iterator.next() self.progress_bar.setValue(self.progress_bar.value() + 1) except StopIteration: self.timer.stop() self.progress_bar.setValue(0)
class Progress(QDialog): file_converted_signal = pyqtSignal() refr_bars_signal = pyqtSignal(int) update_text_edit_signal = pyqtSignal(str) def __init__(self, files, _type, cmd, ffmpeg, size, mntaspect, delete, parent, test=False): """ Keyword arguments: files -- list with dicts containing file names _type -- 'AudioVideo', 'Images' or 'Documents' depending files type cmd -- ffmpeg command, for audio/video conversions ffmpeg -- if True ffmpeg will be used, else avconv for audio/video conversions size -- new image size string of type 'widthxheight' eg. '300x300' for image conversions mntaspect -- boolean indicating whether aspect ratio must be maintained for image conversions delete -- boolean that shows if files must removed after conversion files: Each dict have only one key and one corresponding value. Key is a file to be converted and it's value is the name of the new file that will be converted. Example list: [{"/foo/bar.png" : "/foo/bar.bmp"}, {"/f/bar2.png" : "/f/bar2.bmp"}] """ super(Progress, self).__init__(parent) self.parent = parent self._type = _type self.cmd = cmd self.ffmpeg = ffmpeg self.size = size self.mntaspect = mntaspect self.files = files self.delete = delete if not test: self.step = int(100 / len(files)) self.ok = 0 self.error = 0 self.running = True self.nowLabel = QLabel(self.tr('In progress: ')) totalLabel = QLabel(self.tr('Total:')) self.nowBar = QProgressBar() self.nowBar.setValue(0) self.totalBar = QProgressBar() self.totalBar.setValue(0) self.cancelButton = QPushButton(self.tr('Cancel')) detailsButton = QCommandLinkButton(self.tr('Details')) detailsButton.setSizePolicy(QSizePolicy(QSizePolicy.Fixed)) detailsButton.setCheckable(True) detailsButton.setMaximumWidth(113) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.textEdit = QTextEdit() self.textEdit.setReadOnly(True) self.frame = QFrame() frame_layout = pyqttools.add_to_layout(QHBoxLayout(), self.textEdit) self.frame.setLayout(frame_layout) self.frame.hide() hlayout = pyqttools.add_to_layout(QHBoxLayout(), None, self.nowLabel, None) hlayout2 = pyqttools.add_to_layout(QHBoxLayout(), None, totalLabel, None) hlayout3 = pyqttools.add_to_layout(QHBoxLayout(), detailsButton, line) hlayout4 = pyqttools.add_to_layout(QHBoxLayout(), self.frame) hlayout5 = pyqttools.add_to_layout(QHBoxLayout(), None, self.cancelButton) vlayout = pyqttools.add_to_layout(QVBoxLayout(), hlayout, self.nowBar, hlayout2, self.totalBar, None, hlayout3, hlayout4, hlayout5) self.setLayout(vlayout) detailsButton.toggled.connect(self.resize_dialog) detailsButton.toggled.connect(self.frame.setVisible) self.cancelButton.clicked.connect(self.reject) self.file_converted_signal.connect(self.file_converted) self.refr_bars_signal.connect(self.refresh_progress_bars) self.update_text_edit_signal.connect(self.update_text_edit) self.resize(484, 200) self.setWindowTitle('FF Multi Converter - ' + self.tr('Conversion')) if not test: QTimer.singleShot(0, self.manage_conversions) def resize_dialog(self): """Resize dialog.""" height = 200 if self.frame.isVisible() else 366 self.setMinimumSize(484, height) self.resize(484, height) def update_text_edit(self, txt): """Append txt to the end of current self.textEdit's text.""" current = self.textEdit.toPlainText() self.textEdit.setText(current+txt) self.textEdit.moveCursor(QTextCursor.End) def refresh_progress_bars(self, now_percent): """Refresh the values of self.nowBar and self.totalBar.""" total_percent = int(((now_percent * self.step) / 100) + self.min_value) if now_percent > self.nowBar.value() and not (now_percent > 100): self.nowBar.setValue(now_percent) if (total_percent > self.totalBar.value() and not (total_percent > self.max_value)): self.totalBar.setValue(total_percent) def manage_conversions(self): """ Check whether all files have been converted. If not, it will allow convert_a_file() to convert the next file. """ if not self.running: return if not self.files: self.totalBar.setValue(100) if self.totalBar.value() >= 100: sum_files = self.ok + self.error msg = QMessageBox(self) msg.setStandardButtons(QMessageBox.Ok) msg.setWindowTitle(self.tr("Report")) msg.setText(self.tr("Converted: %1/%2").arg(self.ok).arg(sum_files)) msg.setModal(False) msg.show() self.cancelButton.setText(self.tr("Close")) if self._type == 'Documents': self.parent.docconv = False # doc conversion end else: self.convert_a_file() def file_converted(self): """ Update progress bars values, remove converted file from self.files and call manage_conversions() to continue the process. """ self.totalBar.setValue(self.max_value) self.nowBar.setValue(100) QApplication.processEvents() self.files.pop(0) self.manage_conversions() def reject(self): """ Use standard dialog to ask whether procedure must stop or not. Use the SIGSTOP to stop the conversion process while waiting for user to respond and SIGCONT or kill depending on user's answer. """ if not self.files: QDialog.accept(self) return if self._type == 'AudioVideo': self.process.send_signal(signal.SIGSTOP) self.running = False reply = QMessageBox.question(self, 'FF Multi Converter - ' + self.tr('Cancel Conversion'), self.tr('Are you sure you want to cancel conversion?'), QMessageBox.Yes|QMessageBox.Cancel) if reply == QMessageBox.Yes: if self._type == 'AudioVideo': self.process.kill() if self._type == 'Documents': self.parent.docconv = False self.running = False self.thread.join() QDialog.reject(self) if reply == QMessageBox.Cancel: self.running = True if self._type == 'AudioVideo': self.process.send_signal(signal.SIGCONT) else: self.manage_conversions() def convert_a_file(self): """ Update self.nowLabel's text with current file's name, set self.nowBar value to zero and start the conversion procedure in a second thread using threading module. """ if not self.files: return from_file = self.files[0].keys()[0] to_file = self.files[0].values()[0] if len(from_file) > 40: # split file name if it is too long in order to display it properly text = '.../' + from_file.split('/')[-1] else: text = from_file self.nowLabel.setText(self.tr('In progress:') + ' ' + text) self.nowBar.setValue(0) self.min_value = self.totalBar.value() self.max_value = self.min_value + self.step if not os.path.exists(from_file[1:-1]): self.error += 1 self.file_converted_signal.emit() return def convert(): if self._type == 'AudioVideo': conv_func = self.convert_video params = (from_file, to_file, self.cmd, self.ffmpeg) elif self._type == 'Images': conv_func = self.convert_image params = (from_file, to_file, self.size, self.mntaspect) else: conv_func = self.convert_doc params = (from_file, to_file) if conv_func(*params): self.ok += 1 if self.delete: try: os.remove(from_file[1:-1]) except OSError: pass else: self.error += 1 self.file_converted_signal.emit() self.thread = threading.Thread(target=convert) self.thread.start() def duration_in_seconds(self, duration): """ Return the number of seconds of duration, an integer. Duration is a strinf of type hh:mm:ss.ts """ duration = duration.split('.')[0] hours, mins, secs = duration.split(':') seconds = int(secs) seconds += (int(hours) * 3600) + (int(mins) * 60) return seconds def convert_video(self, from_file, to_file, command, ffmpeg): """ Create the ffmpeg command and execute it in a new process using the subprocess module. While the process is alive, parse ffmpeg output, estimate conversion progress using video's duration. With the result, emit the corresponding signal in order progressbars to be updated. Also emit regularly the corresponding signal in order an textEdit to be updated with ffmpeg's output. Finally, save log information. Return True if conversion succeed, else False. """ assert isinstance(from_file, unicode) and isinstance(to_file, unicode) assert from_file.startswith('"') and from_file.endswith('"') assert to_file.startswith('"') and to_file.endswith('"') converter = 'ffmpeg' if ffmpeg else 'avconv' convert_cmd = '{0} -y -i {1} {2} {3}'.format(converter, from_file, command, to_file) convert_cmd = str(QString(convert_cmd).toUtf8()) self.update_text_edit_signal.emit(unicode(convert_cmd, 'utf-8')+'\n') self.process = subprocess.Popen(shlex.split(convert_cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) final_output = myline = str('') while True: out = str(QString(self.process.stdout.read(1)).toUtf8()) if out == str('') and self.process.poll() is not None: break myline += out if out in (str('\r'), str('\n')): m = re.search("Duration: ([0-9:.]+)", myline) if m: total = self.duration_in_seconds(m.group(1)) n = re.search("time=([0-9:]+)", myline) # time can be of format 'time=hh:mm:ss.ts' or 'time=ss.ts' # depending on ffmpeg version if n: time = n.group(1) if ':' in time: time = self.duration_in_seconds(time) now_sec = int(float(time)) try: self.refr_bars_signal.emit(100 * now_sec / total) except UnboundLocalError, ZeroDivisionError: pass self.update_text_edit_signal.emit(myline) final_output += myline myline = str('') self.update_text_edit_signal.emit('\n\n') return_code = self.process.poll() log_data = {'command' : unicode(convert_cmd, 'utf-8'), 'returncode' : return_code, 'type' : 'VIDEO'} log_lvl = logging.info if return_code == 0 else logging.error log_lvl(unicode(final_output, 'utf-8'), extra=log_data) return return_code == 0
class Qt4SysTrayIcon: def __init__( self ): self.snapshots = snapshots.Snapshots() self.config = self.snapshots.config self.decode = None if len( sys.argv ) > 1: if not self.config.set_current_profile(sys.argv[1]): logger.warning("Failed to change Profile_ID %s" %sys.argv[1], self) self.qapp = qt4tools.create_qapplication(self.config.APP_NAME) translator = qt4tools.get_translator() self.qapp.installTranslator(translator) self.qapp.setQuitOnLastWindowClosed(False) import icon self.icon = icon self.qapp.setWindowIcon(icon.BIT_LOGO) self.status_icon = QSystemTrayIcon(icon.BIT_LOGO) #self.status_icon.actionCollection().clear() self.contextMenu = QMenu() self.menuProfileName = self.contextMenu.addAction(_('Profile: "%s"') % self.config.get_profile_name()) qt4tools.set_font_bold(self.menuProfileName) self.contextMenu.addSeparator() self.menuStatusMessage = self.contextMenu.addAction(_('Done')) self.menuProgress = self.contextMenu.addAction('') self.menuProgress.setVisible(False) self.contextMenu.addSeparator() self.btnDecode = self.contextMenu.addAction(icon.VIEW_SNAPSHOT_LOG, _('decode paths')) self.btnDecode.setCheckable(True) self.btnDecode.setVisible(self.config.get_snapshots_mode() == 'ssh_encfs') QObject.connect(self.btnDecode, SIGNAL('toggled(bool)'), self.onBtnDecode) self.openLog = self.contextMenu.addAction(icon.VIEW_LAST_LOG, _('View Last Log')) QObject.connect(self.openLog, SIGNAL('triggered()'), self.onOpenLog) self.startBIT = self.contextMenu.addAction(icon.BIT_LOGO, _('Start BackInTime')) QObject.connect(self.startBIT, SIGNAL('triggered()'), self.onStartBIT) self.status_icon.setContextMenu(self.contextMenu) self.pixmap = icon.BIT_LOGO.pixmap(24) self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.setValue(0) self.progressBar.setTextVisible(False) self.progressBar.resize(24, 6) self.progressBar.render(self.pixmap, sourceRegion = QRegion(0, -14, 24, 6), flags = QWidget.RenderFlags(QWidget.DrawChildren)) self.first_error = self.config.is_notify_enabled() self.popup = None self.last_message = None self.timer = QTimer() QObject.connect( self.timer, SIGNAL('timeout()'), self.update_info ) self.ppid = os.getppid() def prepare_exit( self ): self.timer.stop() if not self.status_icon is None: self.status_icon.hide() self.status_icon = None if not self.popup is None: self.popup.deleteLater() self.popup = None self.qapp.processEvents() def run( self ): self.status_icon.show() self.timer.start( 500 ) logger.info("[qt4systrayicon] begin loop", self) self.qapp.exec_() logger.info("[qt4systrayicon] end loop", self) self.prepare_exit() def update_info( self ): if not tools.is_process_alive( self.ppid ): self.prepare_exit() self.qapp.exit(0) return message = self.snapshots.get_take_snapshot_message() if message is None and self.last_message is None: message = ( 0, _('Working...') ) if not message is None: if message != self.last_message: self.last_message = message if self.decode: message = (message[0], self.decode.log(message[1])) self.menuStatusMessage.setText('\n'.join(tools.wrap_line(message[1],\ size = 80,\ delimiters = '',\ new_line_indicator = '') \ )) self.status_icon.setToolTip(message[1]) pg = progress.ProgressFile(self.config) if pg.isFileReadable(): pg.load() percent = pg.get_int_value('percent') if percent != self.progressBar.value(): self.progressBar.setValue(percent) self.progressBar.render(self.pixmap, sourceRegion = QRegion(0, -14, 24, 6), flags = QWidget.RenderFlags(QWidget.DrawChildren)) self.status_icon.setIcon(QIcon(self.pixmap)) self.menuProgress.setText(' | '.join(self.getMenuProgress(pg)) ) self.menuProgress.setVisible(True) else: self.status_icon.setIcon(self.icon.BIT_LOGO) self.menuProgress.setVisible(False) def getMenuProgress(self, pg): d = (('sent', _('Sent:')), \ ('speed', _('Speed:')),\ ('eta', _('ETA:')) ) for key, txt in d: value = pg.get_str_value(key, '') if not value: continue yield txt + ' ' + value def onStartBIT(self): profileID = self.config.get_current_profile() cmd = ['backintime-qt4',] if not profileID == '1': cmd += ['--profile-id', profileID] proc = subprocess.Popen(cmd) def onOpenLog(self): dlg = logviewdialog.LogViewDialog(self, systray = True) dlg.decode = self.decode dlg.cb_decode.setChecked(self.btnDecode.isChecked()) dlg.exec_() def onBtnDecode(self, checked): if checked: self.decode = encfstools.Decode(self.config) self.last_message = None self.update_info() else: self.decode = None
class CatalogDialogTool(QObject): """ Tool for managing the search and export functionality """ def __init__(self, iface, dialog_ui, bbox_tool): """ Constructor for the dialog tool :param iface: The QGIS Interface :param dialog_ui: The dialog GUI :param bbox_tool The bounding box tool :return: dialog tool """ QObject.__init__(self, None) self.iface = iface self.dialog_ui = dialog_ui self.bbox_tool = bbox_tool self.progress_bar = None self.progress_message_bar = None self.progress_message_bar_widget = None self.search_thread_pool = QThreadPool() self.search_lock = Lock() self.export_thread_pool = QThreadPool() self.export_lock = Lock() self.query = None self.previous_credentials = None self.export_file = None self.footprint_layer = None self.filters = CatalogFilters(self.dialog_ui) self.dialog_ui.aoi_button.clicked.connect(self.aoi_button_clicked) self.dialog_ui.reset_button.clicked.connect(self.reset_button_clicked) self.dialog_ui.export_button.clicked.connect( self.export_button_clicked) self.bbox_tool.released.connect(self.search) self.model = None def init_progress_bar(self, progress_max): """ Sets up the progress bar for search functionality :return: None """ if not self.progress_message_bar: self.progress_message_bar = self.iface.messageBar().createMessage( "Querying for data") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(progress_max) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignCenter) self.progress_message_bar.layout().addWidget(self.progress_bar) self.progress_message_bar_widget = self.iface.messageBar( ).pushWidget(self.progress_message_bar, self.iface.messageBar().INFO) def init_layers(self): """ Sets up the layers for rendering the items :return: None """ if self.footprint_layer: QgsMapLayerRegistry.instance().removeMapLayer( self.footprint_layer.id()) self.footprint_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "Catalog Footprints", "memory") self.footprint_layer.setCrs(QgsCoordinateReferenceSystem(4326), True) self.footprint_layer.dataProvider().addAttributes( CatalogAcquisitionFeature.get_fields()) QgsMapLayerRegistry.instance().addMapLayer(self.footprint_layer) def clear_widgets(self): """ Clears the progress bar :return: None """ self.progress_bar = None self.progress_message_bar = None if self.progress_message_bar_widget: self.iface.messageBar().popWidget(self.progress_message_bar_widget) self.progress_message_bar_widget = None def is_searching(self): """ Check to see if the system is still searching (checks if there's work in the search thread pool) :return: True if searching; False otherwise """ return self.get_search_active_thread_count() > 0 def is_exporting(self): """ Check to see if the system is still exporting (checks if there's work in the export thread pool) :return: True if searching; False otherwise """ return self.get_export_active_thread_count() > 0 def get_search_active_thread_count(self): """ Gets the number of active threads in the search thread pool :return: """ with self.search_lock: return self.search_thread_pool.activeThreadCount() def get_export_active_thread_count(self): """ Gets the number of active threads in the export thread pool :return: """ with self.export_lock: return self.export_thread_pool.activeThreadCount() def aoi_button_clicked(self): """ Validates and runs the search if validation successful :return: None """ # can't run search during export if self.is_exporting(): self.iface.messageBar().pushMessage( "Error", "Cannot run search while export is running.", level=QgsMessageBar.CRITICAL) # can't run multiple search elif self.is_searching(): self.iface.messageBar().pushMessage( "Error", "Cannot run a new search while a search is running.", level=QgsMessageBar.CRITICAL) else: self.bbox_tool.reset() self.iface.mapCanvas().setMapTool(self.bbox_tool) def reset_button_clicked(self): """ Resets filters. :return: None """ self.reset() def export_button_clicked(self): """ Validates and runs the export if validation successful :return: None """ # can't run export during search if self.is_searching(): self.iface.messageBar().pushMessage( "Error", "Cannot run export while search is running.", level=QgsMessageBar.CRITICAL) # can't run multiple exports elif self.is_exporting(): self.iface.messageBar().pushMessage( "Error", "Cannot run a new export while a export is running.", level=QgsMessageBar.CRITICAL) else: self.export() def search(self, top, bottom, left, right): self.search_thread_pool.waitForDone(0) # validate credentials if they changed errors = [] username, password, api_key, max_items_to_return = SettingsOps.get_settings( ) credentials = [username, password, api_key] if not self.previous_credentials or self.previous_credentials != credentials: SettingsOps.validate_stored_info(username, password, api_key, max_items_to_return, errors) self.previous_credentials = credentials # validate filters if not errors: self.filters.validate(errors) if errors: self.iface.messageBar().pushMessage( "Error", "The following errors occurred: " + "<br />".join(errors), level=QgsMessageBar.CRITICAL) else: self.init_layers() self.dialog_ui.tab_widget.setCurrentIndex(RESULTS_TAB_INDEX) next_x_list = self.drange_list( float(left) + INCREMENTAL_INTERVAL, float(right), INCREMENTAL_INTERVAL) next_y_list = self.drange_list( float(bottom) + INCREMENTAL_INTERVAL, float(top), INCREMENTAL_INTERVAL) self.init_progress_bar(len(next_x_list) * len(next_y_list)) self.model = CatalogTableModel(self.dialog_ui.table_view) self.dialog_ui.table_view.setModel(self.model) self.dialog_ui.table_view.selectionModel( ).selectionChanged.connect(self.selection_changed) if not self.query: self.query = GBDQuery(username=username, password=password, api_key=api_key) filters = self.filters.get_query_filters() time_begin = self.filters.get_datetime_begin() time_end = self.filters.get_datetime_end() current_x = float(left) current_y = float(bottom) for next_x in next_x_list: for next_y in next_y_list: search_runnable = CatalogSearchRunnable( self.query, self.model, self, top=next_y, left=current_x, right=next_x, bottom=current_y, time_begin=time_begin, time_end=time_end, filters=filters) search_runnable.task_object.task_complete.connect( self.on_search_complete) self.search_thread_pool.start(search_runnable) current_y = next_y current_y = bottom current_x = next_x def reset(self): self.filters.remove_all() def export(self): self.export_thread_pool.waitForDone(0) acquisitions = None if self.model is not None: acquisitions = self.model.data if not acquisitions: self.iface.messageBar().pushMessage("Error", "No data to export.", level=QgsMessageBar.CRITICAL) else: # open file ui select_file_ui = QFileDialog() starting_file = self.export_file or os.path.expanduser("~") export_file = select_file_ui.getSaveFileName( None, "Choose output file", starting_file, SELECT_FILTER) if export_file: self.export_file = export_file self.init_progress_bar(0) export_runnable = CatalogExportRunnable( acquisitions, self.export_file) export_runnable.task_object.task_complete.connect( self.on_export_complete) self.export_thread_pool.start(export_runnable) @pyqtSlot() def on_search_complete(self): thread_count = self.get_search_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.dialog_ui.table_view.resizeColumnsToContents() @pyqtSlot() def on_export_complete(self): thread_count = self.get_export_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.iface.messageBar().pushMessage( "Info", 'File export has completed to "%s".' % self.export_file) def selection_changed(self, selected, deselected): self.footprint_layer.startEditing() # draw footprints for selected rows selected_rows = set() for index in selected.indexes(): selected_rows.add(index.row()) for row in selected_rows: acquisition = self.model.get(row) feature_id = self.model.generate_feature_id() self.model.set_feature_id(acquisition, feature_id) feature = CatalogAcquisitionFeature(feature_id, acquisition) self.footprint_layer.dataProvider().addFeatures([feature]) # remove footprints for deselected rows deselected_rows = set() for index in deselected.indexes(): deselected_rows.add(index.row()) feature_ids_to_remove = [] for row in deselected_rows: acquisition = self.model.get(row) feature_id = self.model.get_feature_id(acquisition) feature_ids_to_remove.append(feature_id) self.model.remove_feature_id(acquisition) if feature_ids_to_remove: self.footprint_layer.dataProvider().deleteFeatures( feature_ids_to_remove) self.footprint_layer.commitChanges() self.footprint_layer.updateExtents() self.footprint_layer.triggerRepaint() def drange_list(self, start, stop, step): drange_list = [] r = start while r < stop: drange_list.append(r) r += step if not drange_list: drange_list.append(stop) return drange_list
def runImport(self): ''' Import a GML file ''' # Open GML file = QFile(self.filename) file.open(QIODevice.ReadOnly) gmlcontent = file.readAll() # Guess GML schema gmlschema = QgsGmlSchema() gmlschema.guessSchema(gmlcontent) # XSD Schema xsdschema = PagLuxembourg.main.xsd_schema unknowntypes = list() # Check schema structure table and datatypes layer_structure_errors = list() # Progress bar + message progressMessageBar = PagLuxembourg.main.qgis_interface.messageBar( ).createMessage( QCoreApplication.translate('ImportGML', 'Importing GML')) progress = QProgressBar() progress.setMaximum(len(gmlschema.typeNames())) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) progress2 = QProgressBar() progress2.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress2) PagLuxembourg.main.qgis_interface.messageBar().pushWidget( progressMessageBar, QgsMessageBar.INFO) # Start import session self._startImportSession() # Loop GML types for gmltype in gmlschema.typeNames(): xsdtype = xsdschema.getType(gmltype) if xsdtype is None: unknowntypes.append(gmltype) continue # Progression message progressMessageBar.setText( QCoreApplication.translate('ImportGML', 'Importing {}').format(gmltype)) gmllayer = QgsVectorLayer( u'{}|layername={}'.format(self.filename, gmltype), gmltype, "ogr") # Check schema structure table and datatypes warn_errors, fatal_errors = self.data_checker.checkLayerStructure( gmllayer, xsdtype) if len(fatal_errors) == 0: self._importGmlLayer(gmllayer, xsdtype, progress2) else: for layer, field, message in fatal_errors: self.commit_errors.append(message) progress.setValue(progress.value() + 1) # Commit import session self._commitImport()
def runImport(self): ''' Import a GML file ''' # Open GML file = QFile(self.filename) file.open(QIODevice.ReadOnly) gmlcontent = file.readAll() # Guess GML schema gmlschema = QgsGmlSchema() gmlschema.guessSchema(gmlcontent) # XSD Schema xsdschema = PagLuxembourg.main.xsd_schema unknowntypes = list() # Check schema structure table and datatypes layer_structure_errors = list() # Progress bar + message progressMessageBar = PagLuxembourg.main.qgis_interface.messageBar().createMessage(QCoreApplication.translate('ImportGML','Importing GML')) progress = QProgressBar() progress.setMaximum(len(gmlschema.typeNames())) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) progress2 = QProgressBar() progress2.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress2) PagLuxembourg.main.qgis_interface.messageBar().pushWidget(progressMessageBar, QgsMessageBar.INFO) # Start import session self._startImportSession() # Loop GML types for gmltype in gmlschema.typeNames(): xsdtype = xsdschema.getType(gmltype) if xsdtype is None: unknowntypes.append(gmltype) continue # Progression message progressMessageBar.setText(QCoreApplication.translate('ImportGML','Importing {}').format(gmltype)) gmllayer = QgsVectorLayer('{}|layername={}'.format(self.filename,gmltype), gmltype, "ogr") # Check schema structure table and datatypes warn_errors, fatal_errors = self.data_checker.checkLayerStructure(gmllayer, xsdtype) if len(fatal_errors) == 0: self._importGmlLayer(gmllayer, xsdtype, progress2) else: for layer, field, message in fatal_errors: self.commit_errors.append(message) progress.setValue(progress.value() + 1) # Commit import session self._commitImport()
class Progress(QDialog): file_converted_signal = pyqtSignal() refr_bars_signal = pyqtSignal(int) update_text_edit_signal = pyqtSignal(str) def __init__(self, files, tab, delete, parent, test=False): """ Keyword arguments: files -- list with dicts containing file names tab -- instanseof AudioVideoTab, ImageTab or DocumentTab indicating currently active tab delete -- boolean that shows if files must removed after conversion parent -- parent widget files: Each dict have only one key and one corresponding value. Key is a file to be converted and it's value is the name of the new file that will be converted. Example list: [{"/foo/bar.png" : "/foo/bar.bmp"}, {"/f/bar2.png" : "/f/bar2.bmp"}] """ super(Progress, self).__init__(parent) self.parent = parent self.files = files self.num_total_files = len(self.files) self.tab = tab self.delete = delete if not test: self._type = tab.name self.step = int(100 / len(files)) self.ok = 0 self.error = 0 self.running = True self.nowQL = QLabel(self.tr('In progress: ')) totalQL = QLabel(self.tr('Total:')) self.nowQPBar = QProgressBar() self.nowQPBar.setValue(0) self.totalQPBar = QProgressBar() self.totalQPBar.setValue(0) self.cancelQPB = QPushButton(self.tr('Cancel')) detailsQPB = QCommandLinkButton(self.tr('Details')) detailsQPB.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) detailsQPB.setCheckable(True) detailsQPB.setMaximumWidth(113) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.outputQTE = QTextEdit() self.outputQTE.setReadOnly(True) self.frame = QFrame() frame_layout = utils.add_to_layout('h', self.outputQTE) self.frame.setLayout(frame_layout) self.frame.hide() hlayout = utils.add_to_layout('h', None, self.nowQL, None) hlayout2 = utils.add_to_layout('h', None, totalQL, None) hlayout3 = utils.add_to_layout('h', detailsQPB, line) hlayout4 = utils.add_to_layout('h', self.frame) hlayout5 = utils.add_to_layout('h', None, self.cancelQPB) vlayout = utils.add_to_layout( 'v', hlayout, self.nowQPBar, hlayout2, self.totalQPBar, None, hlayout3, hlayout4, hlayout5 ) self.setLayout(vlayout) detailsQPB.toggled.connect(self.resize_dialog) detailsQPB.toggled.connect(self.frame.setVisible) self.cancelQPB.clicked.connect(self.reject) self.file_converted_signal.connect(self.next_file) self.refr_bars_signal.connect(self.refresh_progress_bars) self.update_text_edit_signal.connect(self.update_text_edit) self.resize(484, 200) self.setWindowTitle('FF Multi Converter - ' + self.tr('Conversion')) if not test: self.get_data() # should be first and not in QTimer.singleShot() QTimer.singleShot(0, self.manage_conversions) def get_data(self): """Collect conversion data from parents' widgets.""" if self._type == 'AudioVideo': self.cmd = self.tab.commandQLE.text() elif self._type == 'Images': width = self.tab.widthQLE.text() self.size = '' self.mntaspect = False if width: height = self.tab.heightQLE.text() self.size = '{0}x{1}'.format(width, height) self.mntaspect = self.tab.imgaspectQChB.isChecked() self.imgcmd = self.tab.commandQLE.text() if self.tab.autocropQChB.isChecked(): self.imgcmd += ' -trim +repage' rotate = self.tab.rotateQLE.text().strip() if rotate: self.imgcmd += ' -rotate {0}'.format(rotate) if self.tab.vflipQChB.isChecked(): self.imgcmd += ' -flip' if self.tab.hflipQChB.isChecked(): self.imgcmd += ' -flop' def resize_dialog(self): """Resize dialog.""" height = 200 if self.frame.isVisible() else 366 self.setMinimumSize(484, height) self.resize(484, height) def update_text_edit(self, txt): """Append txt to the end of current self.outputQTE's text.""" current = self.outputQTE.toPlainText() self.outputQTE.setText(current+txt) self.outputQTE.moveCursor(QTextCursor.End) def refresh_progress_bars(self, now_percent): """Refresh the values of self.nowQPBar and self.totalQPBar.""" total_percent = int(((now_percent * self.step) / 100) + self.min_value) if now_percent > self.nowQPBar.value() and not (now_percent > 100): self.nowQPBar.setValue(now_percent) if (total_percent > self.totalQPBar.value() and not (total_percent > self.max_value)): self.totalQPBar.setValue(total_percent) def manage_conversions(self): """ Check whether all files have been converted. If not, it will allow convert_a_file() to convert the next file. """ if not self.running: return if not self.files: self.totalQPBar.setValue(100) if self.totalQPBar.value() >= 100: sum_files = self.ok + self.error msg = QMessageBox(self) msg.setStandardButtons(QMessageBox.Ok) msg.setWindowTitle(self.tr("Report")) msg.setText(self.tr("Converted: {0}/{1}".format(self.ok,sum_files))) msg.setModal(False) msg.show() self.cancelQPB.setText(self.tr("Close")) else: self.convert_a_file() def next_file(self): """ Update progress bars values, remove converted file from self.files and call manage_conversions() to continue the process. """ self.totalQPBar.setValue(self.max_value) self.nowQPBar.setValue(100) QApplication.processEvents() self.files.pop(0) self.manage_conversions() def reject(self): """ Use standard dialog to ask whether procedure must stop or not. Use the SIGSTOP to stop the conversion process while waiting for user to respond and SIGCONT or kill depending on user's answer. """ if not self.files: QDialog.accept(self) return if self._type == 'AudioVideo': self.process.send_signal(signal.SIGSTOP) self.running = False reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Cancel Conversion'), self.tr('Are you sure you want to cancel conversion?'), QMessageBox.Yes|QMessageBox.Cancel ) if reply == QMessageBox.Yes: if self._type == 'AudioVideo': self.process.kill() self.running = False self.thread.join() QDialog.reject(self) if reply == QMessageBox.Cancel: self.running = True if self._type == 'AudioVideo': self.process.send_signal(signal.SIGCONT) else: self.manage_conversions() def convert_a_file(self): """ Update self.nowQL's text with current file's name, set self.nowQPBar value to zero and start the conversion procedure in a second thread using threading module. """ if not self.files: return from_file = list(self.files[0].keys())[0] to_file = list(self.files[0].values())[0] text = os.path.basename(from_file[1:-1]) num_file = self.num_total_files - len(self.files) + 1 text += ' ({0}/{1})'.format(num_file, self.num_total_files) self.nowQL.setText(self.tr('In progress:') + ' ' + text) self.nowQPBar.setValue(0) self.min_value = self.totalQPBar.value() self.max_value = self.min_value + self.step if not os.path.exists(from_file[1:-1]): self.error += 1 self.file_converted_signal.emit() return def convert(): if self._type == 'AudioVideo': conv_func = self.convert_video params = (from_file, to_file, self.cmd) elif self._type == 'Images': conv_func = self.convert_image params = (from_file, to_file, self.size, self.mntaspect, self.imgcmd) else: conv_func = self.convert_document params = (from_file, to_file) if conv_func(*params): self.ok += 1 if self.delete and not from_file == to_file: try: os.remove(from_file[1:-1]) except OSError: pass else: self.error += 1 self.file_converted_signal.emit() self.thread = threading.Thread(target=convert) self.thread.start() def convert_video(self, from_file, to_file, command): """ Create the ffmpeg command and execute it in a new process using the subprocess module. While the process is alive, parse ffmpeg output, estimate conversion progress using video's duration. With the result, emit the corresponding signal in order progressbars to be updated. Also emit regularly the corresponding signal in order an outputQTE to be updated with ffmpeg's output. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks convert_cmd = '{0} -y -i {1} {2} {3}'.format( self.parent.vidconverter, from_file, command, to_file) self.update_text_edit_signal.emit(convert_cmd + '\n') self.process = subprocess.Popen( shlex.split(convert_cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE ) final_output = myline = '' reader = io.TextIOWrapper(self.process.stdout, encoding='utf8') while True: out = reader.read(1) if out == '' and self.process.poll() is not None: break myline += out if out in ('\r', '\n'): m = re.search("Duration: ([0-9:.]+)", myline) if m: total = utils.duration_in_seconds(m.group(1)) n = re.search("time=([0-9:]+)", myline) # time can be of format 'time=hh:mm:ss.ts' or 'time=ss.ts' # depending on ffmpeg version if n: time = n.group(1) if ':' in time: time = utils.duration_in_seconds(time) now_sec = int(float(time)) try: self.refr_bars_signal.emit(100 * now_sec / total) except (UnboundLocalError, ZeroDivisionError): pass self.update_text_edit_signal.emit(myline) final_output += myline myline = '' self.update_text_edit_signal.emit('\n\n') return_code = self.process.poll() log_data = { 'command' : convert_cmd, 'returncode' : return_code, 'type' : 'VIDEO' } log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0 def convert_image(self, from_file, to_file, size, mntaspect, imgcmd): """ Convert an image using ImageMagick. Create conversion info ("cmd") and emit the corresponding signal in order an outputQTE to be updated with that info. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks resize = '' if size: resize = '-resize {0}'.format(size) if not mntaspect: resize += '\!' imgcmd = ' ' + imgcmd.strip() + ' ' cmd = 'convert {0} {1}{2}{3}'.format(from_file, resize, imgcmd, to_file) self.update_text_edit_signal.emit(cmd + '\n') child = subprocess.Popen( shlex.split(cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE ) child.wait() reader = io.TextIOWrapper(child.stdout, encoding='utf8') final_output = reader.read() self.update_text_edit_signal.emit(final_output+'\n\n') return_code = child.poll() log_data = { 'command' : cmd, 'returncode' : return_code, 'type' : 'IMAGE' } log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0 def convert_document(self, from_file, to_file): """ Create the unoconv command and execute it using the subprocess module. Emit the corresponding signal in order an outputQTE to be updated with unoconv's output. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks to_base, to_ext = os.path.splitext(to_file[1:-1]) cmd = 'unoconv -f {0} -o {1} {2}'.format(to_ext[1:], to_file, from_file) self.update_text_edit_signal.emit(cmd + '\n') child = subprocess.Popen( shlex.split(cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE ) child.wait() reader = io.TextIOWrapper(child.stdout, encoding='utf8') final_output = reader.read() self.update_text_edit_signal.emit(final_output+'\n\n') return_code = child.poll() log_data = { 'command' : cmd, 'returncode' : return_code, 'type' : 'DOCUMENT' } log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0
class Progress(QDialog): file_converted_signal = pyqtSignal() refr_bars_signal = pyqtSignal(int) update_text_edit_signal = pyqtSignal(str) def __init__(self, files, tab, delete, parent, test=False): """ Keyword arguments: files -- list with dicts containing file names tab -- instanseof AudioVideoTab, ImageTab or DocumentTab indicating currently active tab delete -- boolean that shows if files must removed after conversion parent -- parent widget files: Each dict have only one key and one corresponding value. Key is a file to be converted and it's value is the name of the new file that will be converted. Example list: [{"/foo/bar.png" : "/foo/bar.bmp"}, {"/f/bar2.png" : "/f/bar2.bmp"}] """ super(Progress, self).__init__(parent) self.parent = parent self.files = files self.num_total_files = len(self.files) self.tab = tab self.delete = delete if not test: self._type = tab.name self.step = int(100 / len(files)) self.ok = 0 self.error = 0 self.running = True self.nowQL = QLabel(self.tr('In progress: ')) totalQL = QLabel(self.tr('Total:')) self.nowQPBar = QProgressBar() self.nowQPBar.setValue(0) self.totalQPBar = QProgressBar() self.totalQPBar.setValue(0) self.cancelQPB = QPushButton(self.tr('Cancel')) detailsQPB = QCommandLinkButton(self.tr('Details')) detailsQPB.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) detailsQPB.setCheckable(True) detailsQPB.setMaximumWidth(113) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) self.outputQTE = QTextEdit() self.outputQTE.setReadOnly(True) self.frame = QFrame() frame_layout = utils.add_to_layout('h', self.outputQTE) self.frame.setLayout(frame_layout) self.frame.hide() hlayout = utils.add_to_layout('h', None, self.nowQL, None) hlayout2 = utils.add_to_layout('h', None, totalQL, None) hlayout3 = utils.add_to_layout('h', detailsQPB, line) hlayout4 = utils.add_to_layout('h', self.frame) hlayout5 = utils.add_to_layout('h', None, self.cancelQPB) vlayout = utils.add_to_layout('v', hlayout, self.nowQPBar, hlayout2, self.totalQPBar, None, hlayout3, hlayout4, hlayout5) self.setLayout(vlayout) detailsQPB.toggled.connect(self.resize_dialog) detailsQPB.toggled.connect(self.frame.setVisible) self.cancelQPB.clicked.connect(self.reject) self.file_converted_signal.connect(self.next_file) self.refr_bars_signal.connect(self.refresh_progress_bars) self.update_text_edit_signal.connect(self.update_text_edit) self.resize(484, 200) self.setWindowTitle('FF Multi Converter - ' + self.tr('Conversion')) if not test: self.get_data() # should be first and not in QTimer.singleShot() QTimer.singleShot(0, self.manage_conversions) def get_data(self): """Collect conversion data from parents' widgets.""" if self._type == 'AudioVideo': self.cmd = self.tab.commandQLE.text() elif self._type == 'Images': width = self.tab.widthQLE.text() self.size = '' self.mntaspect = False if width: height = self.tab.heightQLE.text() self.size = '{0}x{1}'.format(width, height) self.mntaspect = self.tab.imgaspectQChB.isChecked() self.imgcmd = self.tab.commandQLE.text() if self.tab.autocropQChB.isChecked(): self.imgcmd += ' -trim +repage' rotate = self.tab.rotateQLE.text().strip() if rotate: self.imgcmd += ' -rotate {0}'.format(rotate) if self.tab.vflipQChB.isChecked(): self.imgcmd += ' -flip' if self.tab.hflipQChB.isChecked(): self.imgcmd += ' -flop' def resize_dialog(self): """Resize dialog.""" height = 200 if self.frame.isVisible() else 366 self.setMinimumSize(484, height) self.resize(484, height) def update_text_edit(self, txt): """Append txt to the end of current self.outputQTE's text.""" current = self.outputQTE.toPlainText() self.outputQTE.setText(current + txt) self.outputQTE.moveCursor(QTextCursor.End) def refresh_progress_bars(self, now_percent): """Refresh the values of self.nowQPBar and self.totalQPBar.""" total_percent = int(((now_percent * self.step) / 100) + self.min_value) if now_percent > self.nowQPBar.value() and not (now_percent > 100): self.nowQPBar.setValue(now_percent) if (total_percent > self.totalQPBar.value() and not (total_percent > self.max_value)): self.totalQPBar.setValue(total_percent) def manage_conversions(self): """ Check whether all files have been converted. If not, it will allow convert_a_file() to convert the next file. """ if not self.running: return if not self.files: self.totalQPBar.setValue(100) if self.totalQPBar.value() >= 100: sum_files = self.ok + self.error msg = QMessageBox(self) msg.setStandardButtons(QMessageBox.Ok) msg.setWindowTitle(self.tr("Report")) msg.setText( self.tr("Converted: {0}/{1}".format(self.ok, sum_files))) msg.setModal(False) msg.show() self.cancelQPB.setText(self.tr("Close")) else: self.convert_a_file() def next_file(self): """ Update progress bars values, remove converted file from self.files and call manage_conversions() to continue the process. """ self.totalQPBar.setValue(self.max_value) self.nowQPBar.setValue(100) QApplication.processEvents() self.files.pop(0) self.manage_conversions() def reject(self): """ Use standard dialog to ask whether procedure must stop or not. Use the SIGSTOP to stop the conversion process while waiting for user to respond and SIGCONT or kill depending on user's answer. """ if not self.files: QDialog.accept(self) return if self._type == 'AudioVideo': self.process.send_signal(signal.SIGSTOP) self.running = False reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Cancel Conversion'), self.tr('Are you sure you want to cancel conversion?'), QMessageBox.Yes | QMessageBox.Cancel) if reply == QMessageBox.Yes: if self._type == 'AudioVideo': self.process.kill() self.running = False self.thread.join() QDialog.reject(self) if reply == QMessageBox.Cancel: self.running = True if self._type == 'AudioVideo': self.process.send_signal(signal.SIGCONT) else: self.manage_conversions() def convert_a_file(self): """ Update self.nowQL's text with current file's name, set self.nowQPBar value to zero and start the conversion procedure in a second thread using threading module. """ if not self.files: return from_file = list(self.files[0].keys())[0] to_file = list(self.files[0].values())[0] text = os.path.basename(from_file[1:-1]) num_file = self.num_total_files - len(self.files) + 1 text += ' ({0}/{1})'.format(num_file, self.num_total_files) self.nowQL.setText(self.tr('In progress:') + ' ' + text) self.nowQPBar.setValue(0) self.min_value = self.totalQPBar.value() self.max_value = self.min_value + self.step if not os.path.exists(from_file[1:-1]): self.error += 1 self.file_converted_signal.emit() return def convert(): if self._type == 'AudioVideo': conv_func = self.convert_video params = (from_file, to_file, self.cmd) elif self._type == 'Images': conv_func = self.convert_image params = (from_file, to_file, self.size, self.mntaspect, self.imgcmd) else: conv_func = self.convert_document params = (from_file, to_file) if conv_func(*params): self.ok += 1 if self.delete and not from_file == to_file: try: os.remove(from_file[1:-1]) except OSError: pass else: self.error += 1 self.file_converted_signal.emit() self.thread = threading.Thread(target=convert) self.thread.start() def convert_video(self, from_file, to_file, command): """ Create the ffmpeg command and execute it in a new process using the subprocess module. While the process is alive, parse ffmpeg output, estimate conversion progress using video's duration. With the result, emit the corresponding signal in order progressbars to be updated. Also emit regularly the corresponding signal in order an outputQTE to be updated with ffmpeg's output. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks convert_cmd = '{0} -y -i {1} {2} {3}'.format(self.parent.vidconverter, from_file, command, to_file) self.update_text_edit_signal.emit(convert_cmd + '\n') self.process = subprocess.Popen(shlex.split(convert_cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) final_output = myline = '' reader = io.TextIOWrapper(self.process.stdout, encoding='utf8') while True: out = reader.read(1) if out == '' and self.process.poll() is not None: break myline += out if out in ('\r', '\n'): m = re.search("Duration: ([0-9:.]+)", myline) if m: total = utils.duration_in_seconds(m.group(1)) n = re.search("time=([0-9:]+)", myline) # time can be of format 'time=hh:mm:ss.ts' or 'time=ss.ts' # depending on ffmpeg version if n: time = n.group(1) if ':' in time: time = utils.duration_in_seconds(time) now_sec = int(float(time)) try: self.refr_bars_signal.emit(100 * now_sec / total) except (UnboundLocalError, ZeroDivisionError): pass self.update_text_edit_signal.emit(myline) final_output += myline myline = '' self.update_text_edit_signal.emit('\n\n') return_code = self.process.poll() log_data = { 'command': convert_cmd, 'returncode': return_code, 'type': 'VIDEO' } log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0 def convert_image(self, from_file, to_file, size, mntaspect, imgcmd): """ Convert an image using ImageMagick. Create conversion info ("cmd") and emit the corresponding signal in order an outputQTE to be updated with that info. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks resize = '' if size: resize = '-resize {0}'.format(size) if not mntaspect: resize += '\!' imgcmd = ' ' + imgcmd.strip() + ' ' cmd = 'convert {0} {1}{2}{3}'.format(from_file, resize, imgcmd, to_file) self.update_text_edit_signal.emit(cmd + '\n') child = subprocess.Popen(shlex.split(cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) child.wait() reader = io.TextIOWrapper(child.stdout, encoding='utf8') final_output = reader.read() self.update_text_edit_signal.emit(final_output + '\n\n') return_code = child.poll() log_data = {'command': cmd, 'returncode': return_code, 'type': 'IMAGE'} log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0 def convert_document(self, from_file, to_file): """ Create the unoconv command and execute it using the subprocess module. Emit the corresponding signal in order an outputQTE to be updated with unoconv's output. Finally, save log information. Return True if conversion succeed, else False. """ # note: from_file and to_file names are inside quotation marks to_base, to_ext = os.path.splitext(to_file[1:-1]) cmd = 'unoconv -f {0} -o {1} {2}'.format(to_ext[1:], to_file, from_file) self.update_text_edit_signal.emit(cmd + '\n') child = subprocess.Popen(shlex.split(cmd), stderr=subprocess.STDOUT, stdout=subprocess.PIPE) child.wait() reader = io.TextIOWrapper(child.stdout, encoding='utf8') final_output = reader.read() self.update_text_edit_signal.emit(final_output + '\n\n') return_code = child.poll() log_data = { 'command': cmd, 'returncode': return_code, 'type': 'DOCUMENT' } log_lvl = logging.info if return_code == 0 else logging.error log_lvl(final_output, extra=log_data) return return_code == 0
class Entity(QWidget): def __init__(self, base_image, size, hp=100, pos=(0, 0), parent=None): super().__init__(parent) self._base_label = QLabel(self) self._base_image = base_image self._size = size self._decor_label = None self._decor_pixmap = None self._hp_max = hp self.__pixmap = None """:type: PyQt4.QtGui.QPixmap""" self.__cord_x = pos[0] self.__cord_y = pos[1] self.__angle = 0 self.__hp_bar = QProgressBar(self) self.__hp_bar.setMaximum(self._hp_max) self.__hp_bar.setValue(self._hp_max) self.__hp_bar.setTextVisible(False) self.__hp_bar.setMaximumSize(size[0], 5) self.setAlignment(Qt.AlignCenter) self.updatePixmap() if _debugging: self.setStyleSheet("border: 1px solid black") @property def health(self): return self.__hp_bar.value() @health.setter def health(self, hp): if hp > self._hp_max: hp = self._hp_max elif hp < 0: hp = 0 self.__hp_bar.setValue(hp) @property def angle(self): return self.__angle @angle.setter def angle(self, angle): self.__angle = angle self.updatePixmap() @property def cord_x(self): return self.__cord_x @cord_x.setter def cord_x(self, cord): self.__cord_x = cord self.move(self.cord_x, self.cord_y) @property def cord_y(self): return self.__cord_y @cord_y.setter def cord_y(self, cord): self.__cord_y = cord self.move(self.cord_x, self.cord_y) def hide_hp_bar(self, bool=False): if bool: self.__hp_bar.hide() else: self.__hp_bar.show() def add_decoration(self, path): if path is None: self._decor_label.deleteLater() self._decor_label = None else: self._decor_label = QLabel(self) self._decor_pixmap = QPixmap(path) # self._decor_pixmap = self._decor_pixmap.scaled(self._size[0], self._size[1]) self._decor_pixmap = self._decor_pixmap.transformed(QTransform().rotate(self.angle)) self._decor_label.setPixmap(self._decor_pixmap) self._decor_label.setAlignment(Qt.AlignCenter) self._decor_label.show() def updatePixmap(self): path = get_asset_path(self._base_image) self.__pixmap = QPixmap(path) self.__pixmap = self.__pixmap.scaled(self._size[0], self._size[1]) self.__pixmap = self.__pixmap.transformed(QTransform().rotate(self.angle)) self._base_label.setPixmap(self.__pixmap) self._base_label.show() # self.setFixedSize(self.__pixmap.width(), self.__pixmap.height()) def setFixedSize(self, x, y): super().setFixedSize(x, y) self._base_label.setFixedSize(x, y) def setAlignment(self, alignment): self._base_label.setAlignment(alignment)
class MessageDialog(QWidget): def __init__(self, mailList, jobID = '', sec = 0, parent = None): QWidget.__init__(self, parent) self.prnt = parent self.jobID = jobID self.sec = sec self.frozen = False self.tr = self.prnt.prnt.tr self.setWindowTitle(self.tr._translate('M@il Checker : MailView Dialog')) self.setStyleSheet("QWidget {background: rgba(235,240,255,128);}") self.mailList = QLabel(mailList) self.layout = QVBoxLayout() self.buttonLayout = QHBoxLayout() self.ok = QPushButton(QIcon.fromTheme("dialog-ok"), "", self) self.cancel = QPushButton(QIcon.fromTheme("dialog-cancel"), "", self) self.freezMSG = QPushButton(QIcon.fromTheme("layer-visible-on"), '', self) self.freezMSG.setToolTip(self.tr._translate('Freez message')) self.ok.setMaximumHeight(15) self.freezMSG.setMaximumHeight(15) self.cancel.setMaximumHeight(15) self.ok.clicked.connect(self.accepted) self.freezMSG.clicked.connect(self.freez) self.cancel.clicked.connect(self.rejected) self.buttonLayout.addWidget(self.ok) self.buttonLayout.addWidget(self.freezMSG) self.buttonLayout.addWidget(self.cancel) self.layout.addWidget(self.mailList) if sec : self.lifetime = QProgressBar() self.lifetime.setOrientation(Qt.Horizontal) self.lifetime.setMinimum(0) self.lifetime.setMaximum(sec) self.lifetime.setValue(sec) self.lifetime.setMaximumHeight(7) self.layout.addWidget(self.lifetime) self.lifetimeID = self.startTimer(1000) self.layout.addItem(self.buttonLayout) self.setLayout(self.layout) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setMinimumWidth(100) def accepted(self): self.prnt.prnt.viewJob.emit(self.jobID) if self.prnt.prnt.SoundEnabled : self.prnt.prnt.sound.Accepted.play() self.close() def rejected(self, common = False): if self.prnt.prnt.SoundEnabled and not common : self.prnt.prnt.sound.Cleared.play() self.close() def freez(self, common = False): if self.sec : self.killTimer(self.lifetimeID) self.setStyleSheet("QWidget {background: rgba(100,175,255,25);}") self.frozen = True self.freezMSG.setEnabled(False) if self.prnt.prnt.SoundEnabled and not common : self.prnt.prnt.sound.Frozen.play() def timerEvent(self, ev): if ev.type()==QEvent.Timer : value = self.lifetime.value() #print ev.timerId(), value if value > self.lifetime.minimum() : self.lifetime.setValue(value-1) else : self.close() def isFrozen(self): return self.frozen def closeEvent(self, ev): if ev.type()==QEvent.Close : if self.sec : self.killTimer(self.lifetimeID) self.prnt.checkEmpty.emit(self.jobID) self.prnt.prnt.clearJob.emit(self.jobID) ev.accept() else : ev.ignore()
class filexplorerPluginMain(plugin.Plugin): ' main class for plugin ' def initialize(self, *args, **kwargs): ' class init ' global CONFIG_DIR ec = ExplorerContainer() super(filexplorerPluginMain, self).initialize(*args, **kwargs) self.dock = QDockWidget() self.dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.dock.setWindowTitle("fileXplorer") self.dock.setStyleSheet('QDockWidget::title { text-align: center; }') # search for the truth self.srch = QLineEdit() #self.srch.resize(self.srch.size().height(), self.dock.size().width()) self.srch.setPlaceholderText(' Search for Python files Local or PyPI ') self.srch.returnPressed.connect(self.search) # Disk Usage Bar self.hdbar = QProgressBar() if sys.platform != 'win32': self.hdbar.setMaximum(statvfs(HOME).f_blocks * statvfs(HOME).f_frsize / 1024 / 1024 / 1024) self.hdbar.setValue(statvfs(HOME).f_bfree * statvfs(HOME).f_frsize / 1024 / 1024 / 1024) self.hdbar.setToolTip(str(self.hdbar.value()) + '% Total Disk Use ') #self.hdbar.setStyleSheet('''QProgressBar{background-color: #QLinearGradient(spread:pad,x1:0,y1:0,x2:1,y2:1,stop:0 rgba(255,0,0,99), #stop:1 rgba(9,255,9,200));color:#fff;border:none;border-radius:9px;} #QProgressBar::chunk{background-color:QLinearGradient(spread:pad,y1:0, #x1:0,y2:1,x2:0.27,stop:0 rgb(0,0,0),stop:1 rgb(9,99,255));padding:0; #border:none;border-radius:9px;height:9px;margin:1px;}''') self.model = QDirModel() self.fileView = QColumnView(self.dock) self.fileView.setAlternatingRowColors(True) # self.fileView.setFont(QFont(self.fileView.font().setBold(True))) self.fileView.setIconSize(QSize(32, 32)) self.fileView.setModel(self.model) self.fileView.updatePreviewWidget.connect(self.runfile) self.sli = QSlider() self.sli.setRange(16, 128) self.sli.setValue(32) self.sli.setToolTip('Icon Size: 32 px. Move Slider to change.') self.sli.setOrientation(Qt.Horizontal) self.sli.valueChanged.connect(lambda: self.fileView.setIconSize( QSize(self.sli.value(), self.sli.value()))) self.sli.sliderReleased.connect(lambda: self.sli.setToolTip('Icon Size: ' + str(self.sli.value()))) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((self.srch, self.dock, self.sli, self.hdbar)) ec.addTab(tw, "fileXplorer") #### self.process = QProcess() self.process.finished.connect(self.processFinished) self.preview = QLabel(self.fileView) self.preview.setTextFormat(0) self.preview.setStyleSheet('QLabel{font-size:9px;}') self.preview.setAutoFillBackground(True) self.fileView.setPreviewWidget(self.preview) self.dock.setWidget(self.fileView) # take a shot self.pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self) self.pic.triggered.connect(lambda: QPixmap.grabWindow( QApplication.desktop().winId()).save(QFileDialog.getSaveFileName( self.dock, " Save Screenshot As ... ", HOME, ';;(*.png)'))) # copy time self.tim = QAction(QIcon.fromTheme("user-away"), 'Date and Time to Clipboard', self) self.tim.triggered.connect(lambda: QApplication.clipboard().setText( datetime.now().strftime(" %A %B %d-%m-%Y %H:%M:%S %p "))) # color chooser self.cl = QAction(QIcon.fromTheme("applications-graphics"), 'Color Chooser to Clipboard', self) self.cl.triggered.connect(lambda: QApplication.clipboard().setText( '{}'.format(QColorDialog.getColor().name()))) # icon chooser self.icn = QAction(QIcon.fromTheme("insert-image"), 'Icon Chooser to Clipboard', self) self.icn.triggered.connect(self.iconChooser) # tool bar with actions QToolBar(self.dock).addActions((self.cl, self.icn, self.tim, self.pic)) self.textBrowser = QTextBrowser(self.dock) self.textBrowser.setAutoFillBackground(True) self.textBrowser.setGeometry(self.dock.geometry()) self.textBrowser.hide() def processFinished(self): ' print info of finished processes ' print(" INFO: OK: QProcess finished . . . ") def search(self): ' function to search python files ' # get search results of python filenames local or remote pypi_url = 'http://pypi.python.org/pypi' # pypi query pypi = xmlrpclib.ServerProxy(pypi_url, transport=ProxyTransport()) try: pypi_query = pypi.search({'name': str(self.srch.text()).lower()}) pypi_fls = list(set(['pypi.python.org/pypi/' + a['name'] + ' | pip install ' + a['name'] for a in pypi_query])) except: pypi_fls = '<b> ERROR: Internet not available! ಠ_ಠ </b>' s_out = ('<br> <br> <br> <h3> Search Local Python files: </h3> <hr> ' + # Jedi list comprehension for LOCAL search str(["{}/{}".format(root, f) for root, f in list(itertools.chain(* [list(itertools.product([root], files)) for root, dirs, files in walk(str( QFileDialog.getExistingDirectory(self.dock, 'Open Directory to Search', path.expanduser("~"))))])) if f.endswith(('.py', '.pyw', '.pth')) and not f.startswith('.') and str(self.srch.text()).lower().strip() in f] ).replace(',', '<br>') + '<hr><h3> Search PyPI Python files: </h3>' + # wraped pypi query REMOTE search str(pypi_fls).replace(',', '<br>') + '<hr>Auto-Proxy:ON,DoNotTrack:ON') # print(s_out) try: call('notify-send fileXplorer Searching...', shell=True) except: pass self.srch.clear() self.textBrowser.setGeometry(self.dock.geometry()) self.textBrowser.setHtml(s_out) self.textBrowser.show() tmr = QTimer(self.fileView) tmr.timeout.connect(self.textBrowser.hide) tmr.start(20000) def iconChooser(self): ' Choose a Icon and copy it to clipboard ' # from .std_icon_naming import std_icon_naming as a # prv = QDialog(self.dock) prv.setWindowFlags(Qt.FramelessWindowHint) prv.setAutoFillBackground(True) prv.setGeometry(self.fileView.geometry()) table = QTableWidget(prv) table.setColumnCount(1) table.setRowCount(len(a)) table.verticalHeader().setVisible(True) table.horizontalHeader().setVisible(False) table.setShowGrid(True) table.setIconSize(QSize(128, 128)) for index, icon in enumerate(a): item = QTableWidgetItem(QIcon.fromTheme(icon), '') # item.setData(Qt.UserRole, '') item.setToolTip(icon) table.setItem(index, 0, item) table.clicked.connect(lambda: QApplication.clipboard().setText( 'QtGui.QIcon.fromTheme("{}")'.format(table.currentItem().toolTip()))) table.doubleClicked.connect(prv.close) table.resizeColumnsToContents() table.resizeRowsToContents() QLabel('<h3> <br> 1 Click Copy, 2 Clicks Close </h3>', table) table.resize(prv.size()) prv.exec_() def runfile(self, index): ' run the choosed file ' s = str(file(self.model.filePath(index), 'r').read().strip()) f = str(self.model.filePath(index)) # ctime is NOT crossplatform,metadata change on *nix,creation on Window # http://docs.python.org/library/os.path.html#os.path.getctime m = ''.join((f, N, str(path.getsize(f) / 1024), ' Kilobytes', N, str(len(file(f, 'r').readlines())), ' Lines', N, str(len(s.replace(N, ''))), ' Characters', N, str(len([a for a in sub('[^a-zA-Z0-9 ]', '', s).split(' ') if a != ''])), ' Words', N, str(len([a for a in s if a in punctuation])), ' Punctuation', N, oct(stat(f).st_mode)[-3:], ' Permissions', N, time.ctime(path.getatime(f)), ' Accessed', N, time.ctime(path.getmtime(f)), ' Modified', N, 'Owner: ', str(self.model.fileInfo(index).owner()), N, 'Is Writable: ', str(self.model.fileInfo(index).isWritable()), N, 'Is Executable: ', str(self.model.fileInfo(index).isExecutable()), N, 'Is Hidden: ', str(self.model.fileInfo(index).isHidden()), N, 'Is SymLink: ', str(self.model.fileInfo(index).isSymLink()), N, 'File Extension: ', str(self.model.fileInfo(index).suffix()) )) #print(m) self.preview.setToolTip(m) self.preview.setText(s) self.preview.resize(self.preview.size().width(), self.dock.size().height()) self.process.start('xdg-open {}'.format(f)) if not self.process.waitForStarted(): print((" ERROR: Process {} Failed ! ".format(str(f)))) return
class Entity(QWidget): def __init__(self, base_image, size, hp=100, pos=(0, 0), parent=None): super().__init__(parent) self._base_label = QLabel(self) self._base_image = base_image self._size = size self._decor_label = None self._decor_pixmap = None self._hp_max = hp self.__pixmap = None """:type: PyQt4.QtGui.QPixmap""" self.__cord_x = pos[0] self.__cord_y = pos[1] self.__angle = 0 self.__hp_bar = QProgressBar(self) self.__hp_bar.setMaximum(self._hp_max) self.__hp_bar.setValue(self._hp_max) self.__hp_bar.setTextVisible(False) self.__hp_bar.setMaximumSize(size[0], 5) self.setAlignment(Qt.AlignCenter) self.updatePixmap() if _debugging: self.setStyleSheet("border: 1px solid black") @property def health(self): return self.__hp_bar.value() @health.setter def health(self, hp): if hp > self._hp_max: hp = self._hp_max elif hp < 0: hp = 0 self.__hp_bar.setValue(hp) @property def angle(self): return self.__angle @angle.setter def angle(self, angle): self.__angle = angle self.updatePixmap() @property def cord_x(self): return self.__cord_x @cord_x.setter def cord_x(self, cord): self.__cord_x = cord self.move(self.cord_x, self.cord_y) @property def cord_y(self): return self.__cord_y @cord_y.setter def cord_y(self, cord): self.__cord_y = cord self.move(self.cord_x, self.cord_y) def hide_hp_bar(self, bool=False): if bool: self.__hp_bar.hide() else: self.__hp_bar.show() def add_decoration(self, path): if path is None: self._decor_label.deleteLater() self._decor_label = None else: self._decor_label = QLabel(self) self._decor_pixmap = QPixmap(path) # self._decor_pixmap = self._decor_pixmap.scaled(self._size[0], self._size[1]) self._decor_pixmap = self._decor_pixmap.transformed( QTransform().rotate(self.angle)) self._decor_label.setPixmap(self._decor_pixmap) self._decor_label.setAlignment(Qt.AlignCenter) self._decor_label.show() def updatePixmap(self): path = get_asset_path(self._base_image) self.__pixmap = QPixmap(path) self.__pixmap = self.__pixmap.scaled(self._size[0], self._size[1]) self.__pixmap = self.__pixmap.transformed(QTransform().rotate( self.angle)) self._base_label.setPixmap(self.__pixmap) self._base_label.show() # self.setFixedSize(self.__pixmap.width(), self.__pixmap.height()) def setFixedSize(self, x, y): super().setFixedSize(x, y) self._base_label.setFixedSize(x, y) def setAlignment(self, alignment): self._base_label.setAlignment(alignment)
class CatalogDialogTool(QObject): """ Tool for managing the search and export functionality """ def __init__(self, iface, dialog_ui, bbox_tool): """ Constructor for the dialog tool :param iface: The QGIS Interface :param dialog_ui: The dialog GUI :param bbox_tool The bounding box tool :return: dialog tool """ QObject.__init__(self, None) self.iface = iface self.dialog_ui = dialog_ui self.bbox_tool = bbox_tool self.progress_bar = None self.progress_message_bar = None self.progress_message_bar_widget = None self.search_thread_pool = QThreadPool() self.search_lock = Lock() self.export_thread_pool = QThreadPool() self.export_lock = Lock() self.query = None self.previous_credentials = None self.export_file = None self.footprint_layer = None self.filters = CatalogFilters(self.dialog_ui) self.dialog_ui.aoi_button.clicked.connect(self.aoi_button_clicked) self.dialog_ui.reset_button.clicked.connect(self.reset_button_clicked) self.dialog_ui.export_button.clicked.connect(self.export_button_clicked) self.bbox_tool.released.connect(self.search) self.model = None def init_progress_bar(self, progress_max): """ Sets up the progress bar for search functionality :return: None """ if not self.progress_message_bar: self.progress_message_bar = self.iface.messageBar().createMessage("Querying for data") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(progress_max) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignCenter) self.progress_message_bar.layout().addWidget(self.progress_bar) self.progress_message_bar_widget = self.iface.messageBar().pushWidget(self.progress_message_bar, self.iface.messageBar().INFO) def init_layers(self): """ Sets up the layers for rendering the items :return: None """ if self.footprint_layer: QgsMapLayerRegistry.instance().removeMapLayer(self.footprint_layer.id()) self.footprint_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "Catalog Footprints", "memory") self.footprint_layer.setCrs(QgsCoordinateReferenceSystem(4326), True) self.footprint_layer.dataProvider().addAttributes(CatalogAcquisitionFeature.get_fields()) QgsMapLayerRegistry.instance().addMapLayer(self.footprint_layer) def clear_widgets(self): """ Clears the progress bar :return: None """ self.progress_bar = None self.progress_message_bar = None if self.progress_message_bar_widget: self.iface.messageBar().popWidget(self.progress_message_bar_widget) self.progress_message_bar_widget = None def is_searching(self): """ Check to see if the system is still searching (checks if there's work in the search thread pool) :return: True if searching; False otherwise """ return self.get_search_active_thread_count() > 0 def is_exporting(self): """ Check to see if the system is still exporting (checks if there's work in the export thread pool) :return: True if searching; False otherwise """ return self.get_export_active_thread_count() > 0 def get_search_active_thread_count(self): """ Gets the number of active threads in the search thread pool :return: """ with self.search_lock: return self.search_thread_pool.activeThreadCount() def get_export_active_thread_count(self): """ Gets the number of active threads in the export thread pool :return: """ with self.export_lock: return self.export_thread_pool.activeThreadCount() def aoi_button_clicked(self): """ Validates and runs the search if validation successful :return: None """ # can't run search during export if self.is_exporting(): self.iface.messageBar().pushMessage("Error", "Cannot run search while export is running.", level=QgsMessageBar.CRITICAL) # can't run multiple search elif self.is_searching(): self.iface.messageBar().pushMessage("Error", "Cannot run a new search while a search is running.", level=QgsMessageBar.CRITICAL) else: self.bbox_tool.reset() self.iface.mapCanvas().setMapTool(self.bbox_tool) def reset_button_clicked(self): """ Resets filters. :return: None """ self.reset() def export_button_clicked(self): """ Validates and runs the export if validation successful :return: None """ # can't run export during search if self.is_searching(): self.iface.messageBar().pushMessage("Error", "Cannot run export while search is running.", level=QgsMessageBar.CRITICAL) # can't run multiple exports elif self.is_exporting(): self.iface.messageBar().pushMessage("Error", "Cannot run a new export while a export is running.", level=QgsMessageBar.CRITICAL) else: self.export() def search(self, top, bottom, left, right): self.search_thread_pool.waitForDone(0) # validate credentials if they changed errors = [] username, password, api_key, max_items_to_return = SettingsOps.get_settings() credentials = [username, password, api_key] if not self.previous_credentials or self.previous_credentials != credentials: SettingsOps.validate_stored_info(username, password, api_key, max_items_to_return, errors) self.previous_credentials = credentials # validate filters if not errors: self.filters.validate(errors) if errors: self.iface.messageBar().pushMessage("Error", "The following errors occurred: " + "<br />".join(errors), level=QgsMessageBar.CRITICAL) else: self.init_layers() self.dialog_ui.tab_widget.setCurrentIndex(RESULTS_TAB_INDEX) next_x_list = self.drange_list(float(left) + INCREMENTAL_INTERVAL, float(right), INCREMENTAL_INTERVAL) next_y_list = self.drange_list(float(bottom) + INCREMENTAL_INTERVAL, float(top), INCREMENTAL_INTERVAL) self.init_progress_bar(len(next_x_list) * len(next_y_list)) self.model = CatalogTableModel(self.dialog_ui.table_view) self.dialog_ui.table_view.setModel(self.model) self.dialog_ui.table_view.selectionModel().selectionChanged.connect(self.selection_changed) if not self.query: self.query = GBDQuery(username=username, password=password, api_key=api_key) filters = self.filters.get_query_filters() time_begin = self.filters.get_datetime_begin() time_end = self.filters.get_datetime_end() current_x = float(left) current_y = float(bottom) for next_x in next_x_list: for next_y in next_y_list: search_runnable = CatalogSearchRunnable(self.query, self.model, self, top=next_y, left=current_x, right=next_x, bottom=current_y, time_begin=time_begin, time_end=time_end, filters=filters) search_runnable.task_object.task_complete.connect(self.on_search_complete) self.search_thread_pool.start(search_runnable) current_y = next_y current_y = bottom current_x = next_x def reset(self): self.filters.remove_all() def export(self): self.export_thread_pool.waitForDone(0) acquisitions = None if self.model is not None: acquisitions = self.model.data if not acquisitions: self.iface.messageBar().pushMessage("Error", "No data to export.", level=QgsMessageBar.CRITICAL) else: # open file ui select_file_ui = QFileDialog() starting_file = self.export_file or os.path.expanduser("~") export_file = select_file_ui.getSaveFileName(None, "Choose output file", starting_file, SELECT_FILTER) if export_file: self.export_file = export_file self.init_progress_bar(0) export_runnable = CatalogExportRunnable(acquisitions, self.export_file) export_runnable.task_object.task_complete.connect(self.on_export_complete) self.export_thread_pool.start(export_runnable) @pyqtSlot() def on_search_complete(self): thread_count = self.get_search_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.dialog_ui.table_view.resizeColumnsToContents() @pyqtSlot() def on_export_complete(self): thread_count = self.get_export_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.iface.messageBar().pushMessage("Info", 'File export has completed to "%s".' % self.export_file) def selection_changed(self, selected, deselected): self.footprint_layer.startEditing() # draw footprints for selected rows selected_rows = set() for index in selected.indexes(): selected_rows.add(index.row()) for row in selected_rows: acquisition = self.model.get(row) feature_id = self.model.generate_feature_id() self.model.set_feature_id(acquisition, feature_id) feature = CatalogAcquisitionFeature(feature_id, acquisition) self.footprint_layer.dataProvider().addFeatures([feature]) # remove footprints for deselected rows deselected_rows = set() for index in deselected.indexes(): deselected_rows.add(index.row()) feature_ids_to_remove = [] for row in deselected_rows: acquisition = self.model.get(row) feature_id = self.model.get_feature_id(acquisition) feature_ids_to_remove.append(feature_id) self.model.remove_feature_id(acquisition) if feature_ids_to_remove: self.footprint_layer.dataProvider().deleteFeatures(feature_ids_to_remove) self.footprint_layer.commitChanges() self.footprint_layer.updateExtents() self.footprint_layer.triggerRepaint() def drange_list(self, start, stop, step): drange_list = [] r = start while r < stop: drange_list.append(r) r += step if not drange_list: drange_list.append(stop) return drange_list
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion())); self.config = ConfigHandler(os.path.join(os.path.expanduser('~'), '.pywv/pywv.cfg'), self) self.setStyle(QStyleFactory.create(self.config.loadStyle())) if self.config.loadStyleSheet(): self.setStyleSheet(self.config.loadStyleSheet()) else: self.setStyleSheet("* {}") # without any stylesheet, windowstyles won't apply self.setDockOptions(QMainWindow.AnimatedDocks | QMainWindow.AllowNestedDocks | QMainWindow.AllowTabbedDocks | QMainWindow.VerticalTabs); # self.dummy = QWidget(self) self.setCentralWidget(QWidget(self)) self.pBar = QProgressBar(self) self.pBar.setRange(0, self.config.loadReloadInterval()) self.pBar.setFormat("%v Sekunden") if not self.config.loadAutoload(): self.pBar.hide() self.statusBar = QStatusBar(self) self.setStatusBar(self.statusBar) self.statusBar.addWidget(self.pBar) self.reloadTimer = QTimer(self); self.reloadTimer.setInterval(self.config.loadReloadInterval() * 1000) self.connect(self.reloadTimer, SIGNAL('timeout()'), self.reload_) if self.config.loadAutoload(): self.reloadTimer.start() self.autoloadStatusTimer = QTimer(self) self.autoloadStatusTimer.setInterval(1000) # 1 sec self.connect(self.autoloadStatusTimer, SIGNAL('timeout()'), self.onAutoloadStatus) self.autoloadStatusTimer.start() self.mAction = self.menuBar().addMenu(self.tr("&Action")) self.mAction.addAction(self.tr("&update"), self.reload_, QKeySequence('F5')) self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q') self.mStyle = QMenu(self.tr("&Style"), self) for s in list(QStyleFactory.keys()):# // fill in all available Styles self.mStyle.addAction(s) self.connect(self.mStyle, SIGNAL('triggered(QAction*)'), self.onStyleMenu) self.mOption = self.menuBar().addMenu(self.tr("&Options")) self.mOption.addAction(self.tr("reloadinterval") , self.onReloadTime , 'F8') self.mOption.addAction(self.tr("manage links") , self.onNewLink , 'F6') self.mOption.addSeparator() self.ontopAction = QAction(self.tr("always on &top") , self) self.showTrayAction = QAction(self.tr("show tray &icon") , self) self.closeToTrayAction = QAction(self.tr("close to &tray") , self) self.autoloadAction = QAction(self.tr("auto&load") , self) self.ontopAction.setCheckable(True) self.showTrayAction.setCheckable(True) self.closeToTrayAction.setCheckable(True) self.autoloadAction.setCheckable(True) self.showTrayAction.setChecked (self.config.loadShowTray() ) self.ontopAction.setChecked (self.config.loadOntop() ) self.closeToTrayAction.setChecked(self.config.loadCloseToTray()) self.autoloadAction.setChecked (self.config.loadAutoload() ) self.connect(self.ontopAction , SIGNAL('toggled(bool)') , self.onOntopAction) self.connect(self.showTrayAction , SIGNAL('toggled(bool)') , self.onShowTrayAction) self.connect(self.closeToTrayAction , SIGNAL('toggled(bool)') , self.onCloseToTrayAction) self.connect(self.autoloadAction , SIGNAL('toggled(bool)') , self.onAutoloadAction) self.mOption.addAction(self.ontopAction) self.mOption.addAction(self.showTrayAction) self.mOption.addAction(self.closeToTrayAction) self.mOption.addAction(self.autoloadAction) self.mOption.addSeparator() self.mOption.addMenu(self.mStyle) self.trayIcon = QSystemTrayIcon(QIcon(':/appicon'), self); self.trayMgr = TrayManager(self.config, self.trayIcon) self.connect(self.trayIcon, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.onTrayIcon) if self.config.loadShowTray(): self.trayIcon.show() self.trayIconMenu = QMenu() self.trayIconMenu.addAction(self.tr("e&xit"), self.onExit) self.trayIcon.setContextMenu(self.trayIconMenu) self.mAbout = self.menuBar().addMenu(self.tr("&about")) self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction) self.mAbout.addAction("Qt", self.onAboutQtAction) self.createWidgets() self.resize(self.config.loadWindowSize()) self.restoreState(self.config.loadWindowState()) if self.config.loadIsVisible(): self.show() self.reload_() def __del__(self): self.config.saveWindowState(self.saveState()) def createSingleWidget(self, name): # print 'crt', name, type(name), '\n', self.widgets # print 'crt', name, type(name) links = self.config.loadLinks() if links[name]['type'] == 'generic': self.widgets[name] = GenericWidget(name, self.config, self) else: pluginsAvail = classdirPlugins().all_() for plugin in pluginsAvail: if links[name]['type'] == plugin['class']: pluginClass = plugin['class'] break else: continue exec('self.widgets[name] = %s(name, self.config, self)' % pluginClass) # print(('loaded plugin', self.widgets[name])) self.addDockWidget(0x4, self.widgets[name]) self.widgets[name].reload_() def delWidget(self, name): #print 'del', name, type(name), '\n', self.widgets self.removeDockWidget(self.widgets[name]) self.widgets[name].deleteLater() self.widgets[name] = None del self.widgets[name] def createWidgets(self): self.widgets = {} for name in self.config.loadLinks(): self.createSingleWidget(name) @pyqtSlot() def onExit(self): self.config.saveWindowSize(self.size()) QApplication.exit(); def closeEvent(self, event): self.config.saveWindowSize(self.size()) # QApplication.exit() # tray is visible -> close to tray # else close app if self.trayIcon.isVisible(): event.accept() else: QApplication.exit() return # if close-to-tray is set, do so if self.config.loadCloseToTray(): event.accept() else: QApplication.exit() return; # save this state if self.trayIcon.isVisible(): self.config.saveIsVisible(False) else: self.config.saveIsVisible(True); @pyqtSlot() def reload_(self): for name in self.widgets: self.widgets[name].reload_() self.pBar.setValue(self.config.loadReloadInterval()) self.reloadTimer.start(self.config.loadReloadInterval()*1000) @pyqtSlot() def onAutoloadStatus(self): self.pBar.setValue(self.pBar.value()-1) # print([idx for idx in self.widgets]) def onStyleMenu(self, a): QApplication.setStyle(QStyleFactory.create(a.text())) self.setStyle(QStyleFactory.create(a.text())) self.config.saveStyle(a.text()) def onReloadTime(self): ok = False value, ok = QInputDialog.getInteger(self, self.tr("reloadinterval"), # title self.tr("insert time in s"), # text self.config.loadReloadInterval(), # default 10, # minimum 86400, # maximum (at least once a day) 1, # step ) if ok: self.config.saveReloadInterval(value) self.pBar.setRange(0,self.config.loadReloadInterval()) self.reload_() def onAutoloadAction(self, b): if b: self.reloadTimer.start() self.pBar.show() self.reload_() else: self.reloadTimer.stop() self.pBar.hide() self.config.saveAutoload(b) def onNewLink(self): inp = LinkInput(self.config, self) if inp.exec_(): # sync active widgets for name in inp.modifiedWidgets(): if name in self.widgets: self.delWidget(name) self.createSingleWidget(name) else: self.createSingleWidget(name) # remove deleted # for name in self.widgets: print 'shown', name # for name in self.config.loadLinks(): print 'conf', name todel = [] for name in self.widgets: if name not in self.config.loadLinks(): todel.append(name) for widget in todel: self.delWidget(widget) def onOntopAction(self, b): if b: self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint) else: self.setWindowFlags(Qt.Dialog) self.setWindowIcon(QIcon(':/appicon')) self.show(); self.config.saveOntop(b) def onShowTrayAction(self, b): if b: self.trayIcon.show() else: self.trayIcon.hide() self.config.saveShowTray(b) def onCloseToTrayAction(self, b): self.config.saveCloseToTray(b) def onTrayIcon(self, reason): if reason == QSystemTrayIcon.Trigger: if(self.isVisible()): self.config.saveWindowSize(self.size()) self.hide() self.config.saveIsVisible(False) else: self.show() self.resize(self.config.loadWindowSize()) self.config.saveIsVisible(True) def onAboutAppAction(self): QMessageBox.about(self, self.tr("&about"), self.tr("name %1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion())) def onAboutQtAction(self): QMessageBox.aboutQt(self, self.tr("&about"))
class ObstacleTable(QSortFilterProxyModel): MocMultiplier = 1 SelectionMode = SelectionModeType.Automatic def __init__(self, surfacesList, fileWriter=None): QSortFilterProxyModel.__init__(self) ObstacleTable.SelectionMode = SelectionModeType.Automatic self.manualPolygon = None self.surfacesList = surfacesList self.surfaceType = None self.source = QStandardItemModel() self.setSourceModel(self.source) # tableView.hideColumn(self.IndexObjectId) # tableView.hideColumn(self.IndexLayerId) # tableView.hideColumn(self.IndexX) # tableView.hideColumn(self.IndexY) # tableView.hideColumn(self.IndexLat) # tableView.hideColumn(self.IndexLon) # tableView.hideColumn(self.IndexSurface) self.hideColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.Surface ] self.fixedColumnLabels = [ ObstacleTableColumnType.ObjectId, ObstacleTableColumnType.LayerId, ObstacleTableColumnType.Name, ObstacleTableColumnType.X, ObstacleTableColumnType.Y, ObstacleTableColumnType.Lat, ObstacleTableColumnType.Lon, ObstacleTableColumnType.AltM, ObstacleTableColumnType.AltFt, ObstacleTableColumnType.TreesM, ObstacleTableColumnType.TreesFt ] self.IndexObjectId = 0 self.IndexLayerId = 1 self.IndexName = 2 self.IndexX = 3 self.IndexY = 4 self.IndexLat = 5 self.IndexLon = 6 self.IndexAltM = 7 self.IndexAltFt = 8 self.IndexTreesM = 9 self.IndexTreesFt = 10 self.IndexOcaM = -1 self.IndexOcaFt = -1 self.IndexOchM = -1 self.IndexOchFt = -1 self.IndexObstArea = -1 self.IndexDistInSecM = -1 self.IndexMocAppliedM = -1 self.IndexMocAppliedFt = -1 self.IndexMocMultiplier = -1 self.IndexMocReqM = -1 self.IndexMocReqFt = -1 self.IndexDoM = -1 self.IndexDrM = -1 self.IndexDzM = -1 self.IndexDxM = -1 self.IndexDsocM = -1 self.IndexHeightLossM = -1 self.IndexHeightLossFt = -1 self.IndexAcAltM = -1 self.IndexAcAltFt = -1 self.IndexAltReqM = -1 self.IndexAltReqFt = -1 self.IndexCritical = -1 self.IndexMACG = -1 self.IndexPDG = -1 self.IndexSurfAltM = -1 self.IndexSurfAltFt = -1 self.IndexDifferenceM = -1 self.IndexDifferenceFt = -1 self.IndexIlsX = -1 self.IndexIlsY = -1 self.IndexEqAltM = -1 self.IndexEqAltFt = -1 self.IndexSurfaceName = -1 self.IndexDisregardable = -1 self.IndexCloseIn = -1 self.IndexTag = -1 self.IndexSurface = -1 self.IndexArea = -1 self.IndexHLAppliedM = -1 self.setHeaderLabels() self.setFilterKeyColumn(self.IndexSurface) self.setSortRole(Qt.UserRole + 1) self.layoutChanged.connect(self.setVerticalHeader) self.btnLocate = None self.tblObstacles = None def FilterDisregardableObstacles(self, state): if state: self.setFilterKeyColumn(self.IndexDisregardable) self.setFilterFixedString("Yes") self.setFilterKeyColumn(self.IndexSurface) def setSurfaceType(self, surfaceType): self.surfaceType = surfaceType def setFilterFixedString(self, filterString): QSortFilterProxyModel.setFilterFixedString(self, filterString) self.setVerticalHeader() if self.btnLocate != None and self.tblObstacles != None: selectedIndexes = self.tblObstacles.selectedIndexes() if len(selectedIndexes) == 0: self.btnLocate.setEnabled(False) else: self.btnLocate.setEnabled(True) def setLocateBtn(self, btnLocate): self.btnLocate = btnLocate self.btnLocate.setEnabled(False) self.btnLocate.clicked.connect(self.btnLocateClicked) def btnLocateClicked(self): if self.tblObstacles == None: return selectedIndexes = self.tblObstacles.selectedIndexes() self.locate(selectedIndexes) def tblObstaclesClicked(self, idx): if len(self.tblObstacles.selectedIndexes()) > 0: self.btnLocate.setEnabled(True) def setTableView(self, tblObstacles): self.tblObstacles = tblObstacles self.tblObstacles.setSelectionBehavior(QAbstractItemView.SelectRows) self.tblObstacles.setSortingEnabled(True) self.tblObstacles.clicked.connect(self.tblObstaclesClicked) self.tblObstacles.verticalHeader().sectionClicked.connect( self.tblObstaclesClicked) pass def setHeaderLabels(self): # print self.setHeaderData(1, Qt.Vertical, 1, Qt.DisplayRole) pass def setVerticalHeader(self): for i in range(self.rowCount()): self.setHeaderData(i, Qt.Vertical, i + 1, Qt.DisplayRole) def setHiddenColumns(self, tableView): tableView.hideColumn(self.IndexObjectId) tableView.hideColumn(self.IndexLayerId) tableView.hideColumn(self.IndexX) tableView.hideColumn(self.IndexY) tableView.hideColumn(self.IndexLat) tableView.hideColumn(self.IndexLon) tableView.hideColumn(self.IndexSurface) def getExtentForLocate(self, sourceRow): extent = None surfaceType = None if self.IndexSurface < 0: surfaceType = self.surfaceType else: surfaceType = self.source.item(sourceRow, self.IndexSurface).text() surfaceLayers = QgisHelper.getSurfaceLayers(self.surfaceType) for sfLayer in surfaceLayers: lId = sfLayer.name() if lId.contains(surfaceType): extent = sfLayer.extent() break return extent def clear(self): self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) # self.setHeaderLabels() def locate(self, selectedRowIndexes): if selectedRowIndexes == None or len(selectedRowIndexes) <= 0: return sourceRow = self.mapToSource(selectedRowIndexes[0]).row() objectId = int(self.source.item(sourceRow, self.IndexObjectId).text()) layerId = self.source.item(sourceRow, self.IndexLayerId).text() QgisHelper.selectFeature(layerId, objectId) layer = QgsMapLayerRegistry.instance().mapLayer(layerId) crs = define._canvas.mapSettings().destinationCrs() if crs.mapUnits() == QGis.Meters: x = float(self.source.item(sourceRow, self.IndexX).text()) y = float(self.source.item(sourceRow, self.IndexY).text()) extent = QgsRectangle(x - 350, y - 350, x + 350, y + 350) else: x, result1 = self.source.item(sourceRow, self.IndexLon).data().toDouble() y, result2 = self.source.item(sourceRow, self.IndexLat).data().toDouble() extent = QgsRectangle(x - 0.005, y - 0.005, x + 0.005, y + 0.005) point = QgsPoint(x, y) # extent = self.getExtentForLocate(sourceRow) if extent is None: return QgisHelper.zoomExtent(point, extent, 2) pass def loadObstacles(self, surfaceLayers): if self.source.rowCount() > 0: self.source.clear() self.source.setHorizontalHeaderLabels(self.fixedColumnLabels) demEvaluateAg = None existingDemFlag = False obstacleLayersDEM = QgisHelper.getSurfaceLayers(SurfaceTypes.DEM) obstacleLayers = QgisHelper.getSurfaceLayers(SurfaceTypes.Obstacles) if obstacleLayersDEM != None and len(obstacleLayersDEM) > 0: if QMessageBox.question( None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: self.loadObstaclesDEM(obstacleLayersDEM, surfaceLayers) if obstacleLayers != None and len(obstacleLayers) > 0: # if QMessageBox.question(None, "Question", "Do you want to use DEM for evaluating Obstacle?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: self.loadObstaclesVector(obstacleLayers, surfaceLayers) return True def loadObstaclesDEM(self, obstacleLayersDEM, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading DEM Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 offset = 0.0 self.progress.setValue(0) wCount = 0 hCount = 0 for ly in obstacleLayersDEM: demDataProvider = ly.dataProvider() boundDem = demDataProvider.extent() xMin = boundDem.xMinimum() xMax = boundDem.xMaximum() yMin = boundDem.yMinimum() yMax = boundDem.yMaximum() bound = QgisHelper.getIntersectExtent( ly, QgsGeometry.fromRect(boundDem), surfaceLayers) # boundGeom = QgsGeometry.fromRect(bound) if bound == None: continue block = ly.dataProvider().block(0, ly.extent(), ly.width(), ly.height()) xMinimum = ly.dataProvider().extent().xMinimum() yMaximum = ly.dataProvider().extent().yMaximum() yMinimum = ly.dataProvider().extent().yMinimum() xMaximum = ly.dataProvider().extent().xMaximum() xOffSet = ly.extent().width() / ly.width() yOffSet = ly.extent().height() / ly.height() offset = xOffSet if bound.xMinimum() < xMinimum: wStartNumber = 0 xStartValue = xMinimum else: wStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): hStartNumber = 0 yStartValue = yMaximum else: hStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / xOffSet) hCount = int(math.fabs(yEndValue - yStartValue) / yOffSet) pixelCount = hCount maxium += pixelCount cellSizeWnd = cellsizeWnd(offset, wCount * hCount, maxium * 0.04) cellSizeWnd.setWindowTitle("Input Cell Size") result = cellSizeWnd.exec_() cellRate = 1 if result == 1: offset = cellSizeWnd.cellsize maxium = cellSizeWnd.cellCount + 2 cellRate = cellSizeWnd.cellRate # print cellSizeWnd.textedit1.text() if maxium == 0: return False self.progress.setMaximum(maxium) trees = define._treesDEM tolerance = define._toleranceDEM for obstacleLayer in obstacleLayersDEM: obstacleUnits = obstacleLayer.crs().mapUnits() demDataProvider = obstacleLayer.dataProvider() boundDem = demDataProvider.extent() bound = QgisHelper.getIntersectExtent( obstacleLayer, QgsGeometry.fromRect(boundDem), surfaceLayers) if bound == None: continue boundGeom = QgsGeometry.fromRect(bound) if not boundGeom.intersects(QgsGeometry.fromRect(boundDem)): continue block = obstacleLayer.dataProvider().block(1, obstacleLayer.extent(), obstacleLayer.width(), obstacleLayer.height()) xMinimum = obstacleLayer.extent().xMinimum() yMaximum = obstacleLayer.extent().yMaximum() yMinimum = obstacleLayer.extent().yMinimum() xMaximum = obstacleLayer.extent().xMaximum() xOffSet = obstacleLayer.extent().width() / obstacleLayer.width() yOffSet = obstacleLayer.extent().height() / obstacleLayer.height() if bound.xMinimum() < xMinimum: hStartNumber = 0 xStartValue = xMinimum else: hStartNumber = int((bound.xMinimum() - xMinimum) / xOffSet) xStartValue = bound.xMinimum() if yMaximum < bound.yMaximum(): wStartNumber = 0 yStartValue = yMaximum else: wStartNumber = int((yMaximum - bound.yMaximum()) / yOffSet) yStartValue = bound.yMaximum() if bound.xMaximum() > xMaximum: xEndValue = xMaximum else: xEndValue = bound.xMaximum() if yMinimum > bound.yMinimum(): yEndValue = yMinimum else: yEndValue = bound.yMinimum() wCount = int(math.fabs(xEndValue - xStartValue) / offset) hCount = int(math.fabs(yEndValue - yStartValue) / offset) xPixelWidth = 0.0 yPixelWidth = 0.0 featureID = 0 # i = 0 # k = 0 # altitudeList = [] # self.progress.setValue(0) # while i <= hCount - 1: # j = 0 # while j <= wCount - 1: # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # altitudeList.append(None) # continue # altitude = block.value(j * int(cellRate) + wStartNumber, i * int(cellRate) + hStartNumber) # altitudeList.append(altitude) # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # i += 1 i = 0 k = 0 name = "DEM" semiXoffset = xOffSet / 2 semiYoffset = yOffSet / 2 while i <= hCount - 1: j = 0 while j <= wCount - 1: if block.isNoData(j * cellRate + wStartNumber, i * cellRate + hStartNumber): self.progress.setValue(k) QApplication.processEvents() j += 1 k += 1 continue altitude = block.value(j * cellRate + wStartNumber, i * cellRate + hStartNumber) # # if block.isNoData(j * int(cellRate) + wStartNumber, i* int(cellRate) + hStartNumber): # # j += 1 # # self.progress.setValue(self.progress.value() + 1) # # QApplication.processEvents() # # continue # # altitude = block.value(j* int(cellRate) + wStartNumber, i* int(cellRate)+ hStartNumber) # altitude = altitudeList[k] # if altitude == None: # self.progress.setValue(k) # QApplication.processEvents() # j += 1 # k += 1 # continue point = QgsPoint( xStartValue + (i * cellRate) * xOffSet + semiXoffset, yStartValue - (j * cellRate - 1) * yOffSet - semiYoffset) position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) obstacle = Obstacle(name, position, obstacleLayer.id(), featureID, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree if self.manualPolygon != None: if not self.manualPolygon.contains(obstacle.Position): continue self.checkObstacle(obstacle) self.progress.setValue(k) QApplication.processEvents() j += 1 featureID += 1 k += 1 i += 1 self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def loadObstaclesVector(self, obstacleLayers, surfaceLayers): progressMessageBar = define._messagBar.createMessage( "Loading Vector Obstacles...") self.progress = QProgressBar() self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) define._messagBar.pushWidget(progressMessageBar, define._messagBar.INFO) maxium = 0 self.progress.setValue(0) for ly in obstacleLayers: maxium += ly.featureCount() if maxium == 0: return False self.progress.setMaximum(maxium) for obstacleLayer in obstacleLayers: obstacleUnits = obstacleLayer.crs().mapUnits() features = QgisHelper.getFeaturesInLayerExtent( define._canvas, obstacleLayer, surfaceLayers, SelectionModeType.Automatic) # print len(features) for feature in features: name = feature.attribute("Name").toString() altitude = feature.attribute("Altitude").toFloat()[0] trees = define._trees tolerance = define._tolerance point = feature.geometry().asPoint() position = Point3D() positionDegree = Point3D() if define._canvas.mapUnits() == QGis.Meters: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): position = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: position = Point3D(point.x(), point.y(), altitude) else: if define._canvas.mapSettings().destinationCrs( ) != obstacleLayer.crs(): positionDegree = QgisHelper.CrsTransformPoint( point.x(), point.y(), obstacleLayer.crs(), define._canvas.mapSettings().destinationCrs(), altitude) else: positionDegree = Point3D(point.x(), point.y(), altitude) featureId = feature.id() layerId = obstacleLayer.id() obstacle = Obstacle(name, position, layerId, featureId, None, trees, ObstacleTable.MocMultiplier, tolerance) obstacle.positionDegree = positionDegree # obstacle.positionDegree = positionDegree self.checkObstacle(obstacle) self.progress.setValue(self.progress.value() + 1) QApplication.processEvents() QApplication.processEvents() self.progress.setValue(maxium) define._messagBar.hide() self.manualPolygon = None def addObstacleToModel(self, obstacle, checkResult=None): standardItemList = [] # obstacle.positionDegree = QgisHelper.Meter2Degree(obstacle.Position.x(), obstacle.Position.y()) standardItem = QStandardItem(str(obstacle.featureId)) standardItem.setData(obstacle.featureId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.layerId)) standardItem.setData(obstacle.layerId) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.name)) standardItem.setData(obstacle.name) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.x())) standardItem.setData(obstacle.Position.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.y())) standardItem.setData(obstacle.Position.y()) standardItemList.append(standardItem) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.y())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.y()) standardItemList.append(standardItem) strV = QgisHelper.strDegree(obstacle.positionDegree.y()) value = QVariant(QgisHelper.strDegree(obstacle.positionDegree.x())) standardItem = QStandardItem(value.toString()) standardItem.setData(obstacle.positionDegree.x()) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.Position.z())) standardItem.setData(obstacle.Position.z()) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.Position.z()))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.Position.z())) standardItemList.append(standardItem) standardItem = QStandardItem(str(obstacle.trees)) standardItem.setData(obstacle.trees) standardItemList.append(standardItem) standardItem = QStandardItem( str(Unit.ConvertMeterToFeet(obstacle.trees))) standardItem.setData(Unit.ConvertMeterToFeet(obstacle.trees)) standardItemList.append(standardItem) # for i in range(len(standardItemList), self.source.columnCount()): # standardItemList.append(QStandardItem("None")) self.source.appendRow(standardItemList) standardItem = QStandardItem(str(obstacle.mocMultiplier)) standardItem.setData(obstacle.mocMultiplier) self.source.setItem(self.source.rowCount() - 1, self.IndexMocMultiplier, standardItem) def checkObstacle(self, obstacle): pass def CompareObstacleRows(self, newRow, row, ignore): pass def method_0(self, obstacle_0): colCount = self.columnCount() objectId = range(colCount) objectId[0] = (obstacle_0.featureId) objectId[1] = (obstacle_0.name) objectId[2] = (obstacle_0.position.x()) objectId[3] = (obstacle_0.position.y()) objectId[4] = (obstacle_0.Position.z()) position = obstacle_0.position objectId[6] = (Unit.ConvertMeterToFeet(position.z())) objectId[7] = (obstacle_0.trees) objectId[8] = (Unit.ConvertMeterToFeet(obstacle_0.Trees)) if (self.IndexMocMultiplier > -1): objectId[self.IndexMocMultiplier] = obstacle_0.MocMultiplier return objectId def method_1(self, object_0): pass
def run(self): """ Runs the widget """ project = PagLuxembourg.main.current_project if not project.isPagProject(): return # Check data and selected entities before exporting self.data_checker = DataChecker() if not self.data_checker.run(): return # Select file to export dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setNameFilter("GML file (*.gml)") dialog.setDefaultSuffix("gml") dialog.setWindowTitle(QCoreApplication.translate("ExportGML", "Select the gml location")) dialog.setSizeGripEnabled(False) result = dialog.exec_() if result == 0: return selected_files = dialog.selectedFiles() if len(selected_files) == 0: return # GML filename and directory gml_filename = selected_files[0] gml_directory = os.path.dirname(gml_filename) temp_dir = os.path.join(gml_directory, str(uuid.uuid1())) os.makedirs(temp_dir) # Progress bar progressMessageBar = PagLuxembourg.main.qgis_interface.messageBar().createMessage( QCoreApplication.translate("ExportGML", "Exporting to GML") ) progress = QProgressBar() progress.setMaximum(len(QgsMapLayerRegistry.instance().mapLayers())) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) PagLuxembourg.main.qgis_interface.messageBar().pushWidget(progressMessageBar, QgsMessageBar.INFO) # Create final GML document gml = getDOMImplementation().createDocument( "http://www.interlis.ch/INTERLIS2.3/GML32/INTERLIS", "ili:TRANSFER", None ) gml_root = gml.documentElement gml_root.setAttribute("xmlns:ili", "http://www.interlis.ch/INTERLIS2.3/GML32/INTERLIS") gml_root.setAttribute("xmlns:gml", "http://www.opengis.net/gml/3.2") gml_root.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink") gml_root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") gml_root.setAttribute("xmlns", "http://www.interlis.ch/INTERLIS2.3/GML32/PAG") gml_root.setAttribute("xsi:schemaLocation", "http://www.interlis.ch/INTERLIS2.3/GML32/PAG PAG.xsd") gml_root.setAttribute("gml:id", "x" + str(uuid.uuid1())) # Baskets topic topic_baskets = dict() # 'MODIFICATION PAG' layer definition layer_PAG = project.getModificationPagLayer() # 'MODIFICATION PAG' selection definition selection_PAG = layer_PAG.selectedFeatures() # Counting number entities in 'MODIFICATION PAG' selection entity_count_PAG = layer_PAG.selectedFeatureCount() # Iterates through XSD types for type in PagLuxembourg.main.xsd_schema.types: layer = project.getLayer(type) if layer is None: continue # Progression message progressMessageBar.setText(QCoreApplication.translate("ExportGML", "Exporting {}").format(layer.name())) filename = os.path.join(temp_dir, "{}.gml".format(type.friendlyName())) # Selection test in 'MODIFICATION PAG' QgsVectorFileWriter.writeAsVectorFormat( layer, filename, "utf-8", None, "GML", entity_count_PAG > 0, datasourceOptions=[ "FORMAT=GML3.2", "TARGET_NAMESPACE={}".format(self.DEFAULT_XLMNS), "GML3_LONGSRS=YES", "SRSDIMENSION_LOC=GEOMETRY", "WRITE_FEATURE_BOUNDED_BY=NO", "STRIP_PREFIX=TRUE", "SPACE_INDENTATION=NO", ], ) members = self._getXsdCompliantGml(filename, gml, type) if type.topic() not in topic_baskets: basket = gml.createElement("ili:baskets") gml_root.appendChild(basket) topic = gml.createElement(type.topic()) topic.setAttribute("gml:id", "x" + str(uuid.uuid1())) basket.appendChild(topic) topic_baskets[type.topic()] = topic for member in members: topic_baskets[type.topic()].appendChild(member) progress.setValue(progress.value() + 1) file = open(gml_filename, "wb") file.write(gml.toprettyxml("", "\n", "utf-8")) file.close() shutil.rmtree(temp_dir) # Messages display for number of selected entities if entity_count_PAG == 1: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate("ExportGML", "Success"), QCoreApplication.translate( "ExportGML", "GML export was successful with 1 selected entity in MODIFICATION PAG layer" ), ) elif entity_count_PAG == 0: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate("ExportGML_without", "Success"), QCoreApplication.translate( "ExportGML_without", "GML export was successful without selected entity in MODIFICATION PAG layer" ), ) else: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate("ExportGML_many", "Success"), QCoreApplication.translate( "ExportGML_many", "GML export was successful with {} selected entities in MODIFICATION PAG layer" ).format(entity_count_PAG), )
class Qt4SysTrayIcon: def __init__(self): self.snapshots = snapshots.Snapshots() self.config = self.snapshots.config if len(sys.argv) > 1: if not self.config.set_current_profile(sys.argv[1]): logger.warning("Failed to change Profile_ID %s" % sys.argv[1], self) self.qapp = qt4tools.create_qapplication(self.config.APP_NAME) import icon self.icon = icon self.qapp.setWindowIcon(icon.BIT_LOGO) self.status_icon = QSystemTrayIcon(icon.BIT_LOGO) #self.status_icon.actionCollection().clear() self.contextMenu = QMenu() self.menuProfileName = self.contextMenu.addAction( _('Profile: "%s"') % self.config.get_profile_name()) qt4tools.set_font_bold(self.menuProfileName) self.contextMenu.addSeparator() self.menuStatusMessage = self.contextMenu.addAction(_('Done')) self.menuProgress = self.contextMenu.addAction('') self.menuProgress.setVisible(False) self.contextMenu.addSeparator() self.startBIT = self.contextMenu.addAction(icon.BIT_LOGO, _('Start BackInTime')) QObject.connect(self.startBIT, SIGNAL('triggered()'), self.onStartBIT) self.status_icon.setContextMenu(self.contextMenu) self.pixmap = icon.BIT_LOGO.pixmap(24) self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.setValue(0) self.progressBar.setTextVisible(False) self.progressBar.resize(24, 6) self.progressBar.render(self.pixmap, sourceRegion=QRegion(0, -14, 24, 6), flags=QWidget.RenderFlags( QWidget.DrawChildren)) self.first_error = self.config.is_notify_enabled() self.popup = None self.last_message = None self.timer = QTimer() QObject.connect(self.timer, SIGNAL('timeout()'), self.update_info) self.ppid = os.getppid() def prepare_exit(self): self.timer.stop() if not self.status_icon is None: self.status_icon.hide() self.status_icon = None if not self.popup is None: self.popup.deleteLater() self.popup = None self.qapp.processEvents() def run(self): self.status_icon.show() self.timer.start(500) logger.info("[qt4systrayicon] begin loop", self) self.qapp.exec_() logger.info("[qt4systrayicon] end loop", self) self.prepare_exit() def update_info(self): if not tools.is_process_alive(self.ppid): self.prepare_exit() self.qapp.exit(0) return message = self.snapshots.get_take_snapshot_message() if message is None and self.last_message is None: message = (0, _('Working...')) if not message is None: if message != self.last_message: self.last_message = message self.menuStatusMessage.setText('\n'.join(tools.wrap_line(self.last_message[1],\ size = 80,\ delimiters = '',\ new_line_indicator = '') \ )) self.status_icon.setToolTip(self.last_message[1]) pg = progress.ProgressFile(self.config) if pg.isFileReadable(): pg.load() percent = pg.get_int_value('percent') if percent != self.progressBar.value(): self.progressBar.setValue(percent) self.progressBar.render(self.pixmap, sourceRegion=QRegion(0, -14, 24, 6), flags=QWidget.RenderFlags( QWidget.DrawChildren)) self.status_icon.setIcon(QIcon(self.pixmap)) self.menuProgress.setText(' | '.join(self.getMenuProgress(pg))) self.menuProgress.setVisible(True) else: self.status_icon.setIcon(self.icon.BIT_LOGO) self.menuProgress.setVisible(False) def getMenuProgress(self, pg): d = (('sent', _('Sent:')), \ ('speed', _('Speed:')),\ ('eta', _('ETA:')) ) for key, txt in d: value = pg.get_str_value(key, '') if not value: continue yield txt + ' ' + value def onStartBIT(self): profileID = self.config.get_current_profile() cmd = [ 'backintime-qt4', ] if not profileID == '1': cmd += ['--profile-id', profileID] proc = subprocess.Popen(cmd)
def run(self): ''' Runs the widget ''' project = PagLuxembourg.main.current_project if not project.isPagProject(): return # Check data and selected entities before exporting self.data_checker = DataChecker() if not self.data_checker.run(): return # Select file to export dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setNameFilter('GML file (*.gml)') dialog.setDefaultSuffix('gml') dialog.setWindowTitle( QCoreApplication.translate('ExportGML', 'Select the gml location')) dialog.setSizeGripEnabled(False) result = dialog.exec_() if result == 0: return selected_files = dialog.selectedFiles() if len(selected_files) == 0: return # GML filename and directory gml_filename = selected_files[0] gml_directory = os.path.dirname(gml_filename) temp_dir = os.path.join(gml_directory, str(uuid.uuid1())) os.makedirs(temp_dir) # Progress bar progressMessageBar = PagLuxembourg.main.qgis_interface.messageBar( ).createMessage( QCoreApplication.translate('ExportGML', 'Exporting to GML')) progress = QProgressBar() progress.setMaximum(len(QgsMapLayerRegistry.instance().mapLayers())) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) PagLuxembourg.main.qgis_interface.messageBar().pushWidget( progressMessageBar, QgsMessageBar.INFO) # Create final GML document gml = getDOMImplementation().createDocument( 'http://www.interlis.ch/INTERLIS2.3/GML32/INTERLIS', 'ili:TRANSFER', None) gml_root = gml.documentElement gml_root.setAttribute( 'xmlns:ili', 'http://www.interlis.ch/INTERLIS2.3/GML32/INTERLIS') gml_root.setAttribute('xmlns:gml', 'http://www.opengis.net/gml/3.2') gml_root.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink') gml_root.setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') gml_root.setAttribute('xmlns', 'http://www.interlis.ch/INTERLIS2.3/GML32/PAG') gml_root.setAttribute( 'xsi:schemaLocation', 'http://www.interlis.ch/INTERLIS2.3/GML32/PAG PAG.xsd') gml_root.setAttribute('gml:id', 'x' + str(uuid.uuid1())) # Baskets topic topic_baskets = dict() # 'MODIFICATION PAG' layer definition layer_PAG = project.getModificationPagLayer() # 'MODIFICATION PAG' selection definition selection_PAG = layer_PAG.selectedFeatures() # Counting number entities in 'MODIFICATION PAG' selection entity_count_PAG = layer_PAG.selectedFeatureCount() # Iterates through XSD types for type in PagLuxembourg.main.xsd_schema.types: layer = project.getLayer(type) if layer is None: continue # Progression message progressMessageBar.setText( QCoreApplication.translate('ExportGML', 'Exporting {}').format( layer.name())) filename = os.path.join(temp_dir, '{}.gml'.format(type.friendlyName())) # Selection test in 'MODIFICATION PAG' QgsVectorFileWriter.writeAsVectorFormat( layer, filename, 'utf-8', None, 'GML', entity_count_PAG > 0, datasourceOptions=[ 'FORMAT=GML3.2', 'TARGET_NAMESPACE={}'.format(self.DEFAULT_XLMNS), 'GML3_LONGSRS=YES', 'SRSDIMENSION_LOC=GEOMETRY', 'WRITE_FEATURE_BOUNDED_BY=NO', 'STRIP_PREFIX=TRUE', 'SPACE_INDENTATION=NO' ]) members = self._getXsdCompliantGml(filename, gml, type) if type.topic() not in topic_baskets: basket = gml.createElement('ili:baskets') gml_root.appendChild(basket) topic = gml.createElement(type.topic()) topic.setAttribute('gml:id', 'x' + str(uuid.uuid1())) basket.appendChild(topic) topic_baskets[type.topic()] = topic for member in members: topic_baskets[type.topic()].appendChild(member) progress.setValue(progress.value() + 1) file = open(gml_filename, 'wb') file.write(gml.toprettyxml('', '\n', 'utf-8')) file.close() shutil.rmtree(temp_dir) # Messages display for number of selected entities if entity_count_PAG == 1: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate('ExportGML', 'Success'), QCoreApplication.translate( 'ExportGML', 'GML export was successful with 1 selected entity in MODIFICATION PAG layer' )) elif entity_count_PAG == 0: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate('ExportGML_without', 'Success'), QCoreApplication.translate( 'ExportGML_without', 'GML export was successful without selected entity in MODIFICATION PAG layer' )) else: PagLuxembourg.main.qgis_interface.messageBar().clearWidgets() PagLuxembourg.main.qgis_interface.messageBar().pushSuccess( QCoreApplication.translate('ExportGML_many', 'Success'), QCoreApplication.translate( 'ExportGML_many', 'GML export was successful with {} selected entities in MODIFICATION PAG layer' ).format(entity_count_PAG))