Exemple #1
0
def get_folder_filepath(
    parent,
    message: str,
    *,
    show_files: bool = True,
    directory: str = '',
    exists: bool = True,
    native: bool = False,
) -> Path or None:
    options = QFileDialog.DontResolveSymlinks

    if not native:
        options |= QFileDialog.DontUseNativeDialog

    if not show_files:
        options |= QFileDialog.ShowDirsOnly

    dialog = QFileDialog(parent, caption=message, directory=directory)
    dialog.setFileMode(QFileDialog.Directory)
    dialog.setOptions(options)

    if not exists:
        dialog.setAcceptMode(QFileDialog.AcceptSave)

    if dialog.exec_() == QFileDialog.Accepted:
        folder_path = dialog.selectedFiles()[0]

        if folder_path:
            return Path(folder_path)
Exemple #2
0
    def Download(self):
        from PyQt5.QtWidgets import QFileDialog, QDialog

        try:
            opt = QtWidgets.QFileDialog.Options()
            opt |= QtWidgets.QFileDialog.DontUseSheet
            dialog = QFileDialog()
            dialog.setOptions(opt)
            dialog.setDirectory(self.userDPath)
            path, _ = QtWidgets.QFileDialog.getSaveFileName(
                None,
                "Where to Download?",
                "MyChangeAvatar.png",
                "PNG (*.png)",
                options=opt,
            )
            if path:
                import shutil

                shutil.copyfile(
                    self.AppSettingDir +
                    "prxUserMeta\\MegaSRX\\metaprodata\\" +
                    self.user[self.currentUserCounter] + ".png",
                    path,
                )
        except Exception as e:
            self.logit(str(e), "error")
Exemple #3
0
def readMap(filename=None):
    """
    Import alternate map file.
    """
    if filename is None:
        fd = QFileDialog(None, "Load map file")
        fd.setLabelText(QFileDialog.Accept, "Import")
        fd.setNameFilters(["Map Files (*.txt)", "All Files (*)"])
        fd.setOptions(QFileDialog.DontUseNativeDialog)
        fd.setViewMode(QFileDialog.List)
        fd.setFileMode(QFileDialog.ExistingFile)
        if fd.exec():
            fileNames = fd.selectedFiles()
            filename = fileNames[0]
    else:
        pass
    numlines = sum(1 for line in open(filename))
    if numlines < 2:
        print('Map file is empty.')
        return
    else:
        print('Map has ', numlines, ' lines.')
    # read the first line - target coords in HH:MM:SS.SS, DD:MM:SS.SS
    file = open(filename)
    line = file.readline()
    if len(line.split()) != 6:
        print('File is not a map file.')
        return
    file.close()
    mapListPath = filename
    numMapPoints = numlines - 1
    return numMapPoints, mapListPath
Exemple #4
0
    def open_file_dialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        options |= QFileDialog.ShowDirsOnly
        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.DirectoryOnly)
        dialog.setOptions(options)
        file_view = dialog.findChild(QListView, 'listView')

        # to make it possible to select multiple directories:
        if file_view:
            file_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        f_tree_view = dialog.findChild(QTreeView)
        if f_tree_view:
            f_tree_view.setSelectionMode(QAbstractItemView.ExtendedSelection)

        if dialog.exec():
            paths = dialog.selectedFiles()
            for patient_data_directory in paths:
                patient_identifier = os.path.basename(patient_data_directory)
                if patient_identifier not in self.patient_data_sets:
                    dp_file_path = os.path.join(patient_data_directory,
                                                'result_images',
                                                'exported_data',
                                                'diffusion_parameters.mat')
                    if os.path.exists(dp_file_path):
                        data = loadmat(dp_file_path)
                        self.load_data(patient_identifier, data)
                    else:
                        error_dialog = QtWidgets.QErrorMessage()
                        error_dialog.showMessage(
                            f'File path error: {patient_data_directory} does not contain diffusion '
                            f'parameters')
                        error_dialog.exec_()
Exemple #5
0
def writeSct(sctPars, sctfile):
    """
    Write a *.sct file from a dictionary.
    """
    fd = QFileDialog(None, "Save updated .sct file")
    fd.setLabelText(QFileDialog.Accept, "Export as")
    fd.setNameFilters(["Scan description (*.sct)", "All Files (*)"])
    fd.setOptions(QFileDialog.DontUseNativeDialog)
    fd.setViewMode(QFileDialog.List)
    fd.selectFile(sctfile)
    if fd.exec():
        #fd.getSaveFileName(directory=sctfile)
        filenames = fd.selectedFiles()
        filename = filenames[0]
        if filename[-4:] != '.sct':
            filename += '.sct'
        print("Exporting scan description to file: ", filename)
        with io.open(filename, mode='w') as f:
            for key in sctPars.keys():
                if sctPars[key] != "":
                    #print(sctPars[key])
                    f.write("{0:25s} #{1:s}\n".format(sctPars[key],
                                                      key.upper()))
        print('File ' + filename + ' exported.')
        msg = "File " + filename + ' exported.\n'
    else:
        msg = 'Updated .sct file not saved.\n'
    return msg
Exemple #6
0
 def write_csv(self):
     dialog = QFileDialog(self, 'Write csv file', '.', '*.csv')
     dialog.setDefaultSuffix('csv')
     dialog.setAcceptMode(QFileDialog.AcceptSave)
     dialog.setOptions(QFileDialog.DontConfirmOverwrite)
     if dialog.exec() == QDialog.Accepted:
         name = dialog.selectedFiles()
         fh = open(name[0], 'w')
         f = self.dut.freq
         o = np.interp(f,
                       self.open.freq,
                       self.open.data,
                       period=self.open.period)
         s = np.interp(f,
                       self.short.freq,
                       self.short.data,
                       period=self.short.period)
         l = np.interp(f,
                       self.load.freq,
                       self.load.data,
                       period=self.load.period)
         d = self.dut.data
         fh.write(
             'frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n'
         )
         for i in range(f.size):
             fh.write(
                 '0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n'
                 % (f[i] * 1000, o.real[i], o.imag[i], s.real[i], s.imag[i],
                    l.real[i], l.imag[i], d.real[i], d.imag[i]))
         fh.close()
Exemple #7
0
def getSaveFileNameWithSuffix(parent,
                              caption,
                              directory,
                              filter,
                              options=None,
                              selectedFilter=None,
                              defaultSuffix=None):
    """
    A reimplemented version of QFileDialog.getSaveFileName() because we would like to make use
    of the QFileDialog.defaultSuffix property that getSaveFileName() does not let us adjust.

    Note: knowing the selected filter is not an invitation to change the chosen filename later.
    """
    dialog = QFileDialog(parent=parent,
                         caption=caption,
                         directory=directory,
                         filter=filter)
    if options:
        dialog.setOptions(options)
    if defaultSuffix:
        dialog.setDefaultSuffix(defaultSuffix)
    dialog.setFileMode(QFileDialog.AnyFile)
    if hasattr(dialog, 'setSupportedSchemes'):  # Pre-Qt5.6 lacks this.
        dialog.setSupportedSchemes(("file", ))
    dialog.setAcceptMode(QFileDialog.AcceptSave)
    if selectedFilter:
        dialog.selectNameFilter(selectedFilter)
    if (dialog.exec() == QFileDialog.Accepted):
        return dialog.selectedFiles()[0], dialog.selectedNameFilter()
    return None, None
Exemple #8
0
    def chooseFiles(self, mode, oldFiles, acceptedMimeTypes):
        #Format acceptedMimeTypes
        nameFiltersString = ""
        for x in acceptedMimeTypes:
            nameFiltersString += "*" + x + " "
        uploadDialog = QFileDialog()

        if (args.downloadPath):
            uploadDialog.setDirectory(args.downloadPath)

        uploadDialog.setNameFilters([nameFiltersString])
        uploadDialog.setFileMode(QFileDialog.ExistingFile)
        uploadDialog.setAcceptMode(QFileDialog.AcceptOpen)

        options = QFileDialog.Options()
        options |= QFileDialog.ReadOnly
        options |= QFileDialog.DontUseNativeDialog

        uploadDialog.setOptions(options)

        if uploadDialog.exec_():
            fileName = uploadDialog.selectedFiles()
            return fileName

        return [""]
Exemple #9
0
    def on_saveButton_clicked(self):
        if PATH.IS_SCREEN:
            DIR = PATH.SCREENDIR
        else:
            DIR = PATH.PANELDIR

        dialog = QFileDialog(self)
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        dialog.setOptions(options)
        dialog.setDirectory(DIR)
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("style files (*.qss *.style);;All files (*.*)")
        dialog.setWindowTitle('Save StyleSheet')
        dialog.setLabelText(QFileDialog.Accept, "Save")

        # sidebar links
        urls = []
        urls.append(QUrl.fromLocalFile(os.path.expanduser('~')))
        urls.append(QUrl.fromLocalFile(DIR))
        urls.append(
            QUrl.fromLocalFile(
                os.path.join(os.getcwd(), 'qtvcp/screens', PATH.BASENAME)))

        dialog.setSidebarUrls(urls)

        result = dialog.exec_()
        if result:
            fileName = dialog.selectedFiles()[0]
            self.saveStyleSheet(fileName)
Exemple #10
0
def FileDialog(directory='', forOpen=True, fmt='', isFolder=False):
    options = QFileDialog.Options()
    options |= QFileDialog.DontUseNativeDialog
    options |= QFileDialog.DontUseCustomDirectoryIcons
    dialog = QFileDialog()
    dialog.setOptions(options)

    dialog.setFilter(dialog.filter() | QtCore.QDir.Hidden)

    # ARE WE TALKING ABOUT FILES OR FOLDERS
    if isFolder:
        dialog.setFileMode(QFileDialog.DirectoryOnly)
    else:
        dialog.setFileMode(QFileDialog.AnyFile)
    # OPENING OR SAVING
    dialog.setAcceptMode(QFileDialog.AcceptOpen) if forOpen else dialog.setAcceptMode(QFileDialog.AcceptSave)

    # SET FORMAT, IF SPECIFIED
    if fmt != '' and isFolder is False:
        dialog.setDefaultSuffix(fmt)
        dialog.setNameFilters([f'{fmt} (*.{fmt})'])

    # SET THE STARTING DIRECTORY
    if directory != '':
        dialog.setDirectory(str(directory))
    else:
        dialog.setDirectory(str(ROOT_DIR))


    if dialog.exec_() == QDialog.Accepted:
        path = dialog.selectedFiles()[0]  # returns a list
        return path
    else:
        return ''
Exemple #11
0
def conv_save_pressed(P, W):
    head = _translate('HandlerClass', 'Save Error')
    with open(P.fNgc, 'r') as inFile:
        for line in inFile:
            if '(new conversational file)' in line:
                msg0 = _translate('HandlerClass',
                                  'An empty file cannot be saved')
                P.dialog_show_ok(QMessageBox.Warning, '{}'.format(head),
                                 '{}\n'.format(msg0))
                return
    P.vkb_show()
    dlg = QFileDialog(W)
    dlg.setOptions(QFileDialog.DontUseNativeDialog)
    dlg.setAcceptMode(QFileDialog.AcceptSave)
    dlg.setNameFilters(['G-Code Files (*.ngc *.nc *.tap)', 'All Files (*)'])
    dlg.setDefaultSuffix('ngc')
    dlg.setDirectory(P.programPrefix)
    name = ''
    if dlg.exec_():
        name = dlg.selectedFiles()[0]
    if name:
        COPY(P.fNgc, name)
        W.conv_save.setEnabled(False)
        conv_enable_tabs(P, W)
    P.vkb_show(True)
Exemple #12
0
 def saveRotatedFits(self, name_orig):
     """ Save the downloaded FITS image """
     
     filename, file_extension = os.path.splitext(name_orig)
     #fileroot = os.path.basename(filename)
     #print('file root is ', fileroot)
     print('Saving ',filename+'_NE.fits')
     # Dialog to save file
     fd = QFileDialog()
     fd.setLabelText(QFileDialog.Accept, "Save as")
     fd.setNameFilters(["Fits Files (*.fits)","All Files (*)"])
     fd.setOptions(QFileDialog.DontUseNativeDialog)
     fd.setViewMode(QFileDialog.List)
     fd.selectFile(filename+'_NE.fits')        
     if (fd.exec()):
         fileName = fd.selectedFiles()
         outfile = fileName[0]
         filename, file_extension = os.path.splitext(outfile)
         # basename = os.path.basename(filename)            
         # Primary header
         image = self.data
         wcs   = self.wcs
         header = wcs.to_header()
         header.remove('WCSAXES')
         header['INSTRUME'] = (self.source, 'Instrument')
         hdu = fits.PrimaryHDU(image)
         hdu.header.extend(header)
         hdul = fits.HDUList([hdu])
         hdul.writeto(outfile,overwrite=True) # clobber true  allows rewriting
         hdul.close()
Exemple #13
0
    def openLocalCube(self):
        """ Open local spectral cube."""

        # Open a dialog
        fd = QFileDialog()
        fd.setLabelText(QFileDialog.Accept, "Import")
        fd.setNameFilters(["Fits Files (*.fits)", "All Files (*)"])
        fd.setOptions(QFileDialog.DontUseNativeDialog)
        fd.setViewMode(QFileDialog.List)
        fd.setFileMode(QFileDialog.ExistingFile)

        if (fd.exec()):
            filenames = fd.selectedFiles()
            cube_file = filenames[0]
            print("File selected is: ", filenames[0])
            try:
                print('opening ', cube_file)
                self.data = specCube(cube_file)
                self.wcs = self.data.wcs
                # Check if coordinates are inside the image
                x, y = self.wcs.wcs_world2pix(self.lon, self.lat, 0)
                print('x y ', x, y)
                if x >= 0 and x <= self.data.nx and y >= 0 and y <= self.data.ny:
                    print('Source inside the FITS cube')
                else:
                    self.data = None
                    self.wcs = None
                    print('The selected  FITS is not a valid file')
            except:
                self.data = None
                self.wcs = None
                print('The selected  FITS is not a valid file')
Exemple #14
0
def exportContours(self):
    """Export defined contours."""
    itab = self.itabs.currentIndex()
    ic0 = self.ici[itab]
    ih0 = self.ihi[itab]
    if ic0.contour is not None:
        if ic0.title in ['Flux', 'Coverage map', 'Flux [no atm. corr.]']:
            source = self.specCube.instrument
        else:
            source = ic0.title
        info = [('source', source), ('levels', ih0.levels)]
        data = OrderedDict(info)
        # Open a dialog
        fd = QFileDialog()
        fd.setLabelText(QFileDialog.Accept, "Export as")
        fd.setNameFilters(["Json Files (*.json)", "All Files (*)"])
        fd.setOptions(QFileDialog.DontUseNativeDialog)
        fd.setViewMode(QFileDialog.List)
        if (fd.exec()):
            filenames = fd.selectedFiles()
            filename = filenames[0]
            if filename[-5:] != '.json':
                filename += '.json'
            print("Exporting contour levels to file: ", filename)
            with io.open(filename, mode='w') as f:
                str_ = json.dumps(data,
                                  indent=2,
                                  separators=(',', ': '),
                                  ensure_ascii=False,
                                  cls=MyEncoder)
                f.write(str_)
            self.sb.showMessage("Aperture exported in file " + filename, 3000)
    else:
        return
Exemple #15
0
def get_open_dialog(directory_mode=False, parent=None, name_filter="full") -> QFileDialog:
    fip = FileIconProvider()
    dialog = QFileDialog(parent)
    dialog.setIconProvider(fip)
    dialog.setDirectory(RECENT_PATH)

    if directory_mode:
        dialog.setFileMode(QFileDialog.Directory)
        dialog.setWindowTitle("Open Folder")
    else:
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setWindowTitle("Open Files")
        if name_filter == "full":
            name_filter = "All files (*);;Complex (*.complex);;" \
                          "Complex16 unsigned (*.complex16u);;" \
                          "Complex16 signed (*.complex16s);;" \
                          "Wave (*.wav);;" \
                          "Protocols (*.proto.xml *.proto);;" \
                          "Fuzzprofiles (*.fuzz.xml *.fuzz);;" \
                          "Plain bits (*.txt);;" \
                          "Tar Archives (*.tar *.tar.gz *.tar.bz2);;" \
                          "Zip Archives (*.zip)"
        elif name_filter == "proto":
            name_filter = "Protocols (*.proto.xml *.proto);;"
        elif name_filter == "fuzz":
            name_filter = "Fuzzprofiles (*.fuzz.xml *.fuzz);;"

        dialog.setNameFilter(name_filter)

    dialog.setOptions(QFileDialog.DontResolveSymlinks)
    dialog.setViewMode(QFileDialog.Detail)

    return dialog
Exemple #16
0
def _fileDialog(acceptMode,
                fileMode,
                parent=None,
                caption='',
                directory='',
                filters=(),
                selectedFilter=None,
                options=0):

    nameFilters = make_filters(filters)

    dialog = QFileDialog(parent, caption, directory)
    dialog.setNameFilters(nameFilters)
    dialog.setAcceptMode(acceptMode)
    dialog.setFileMode(fileMode)
    dialog.setOptions(QFileDialog.Options(options))
    if selectedFilter is not None:
        dialog.selectNameFilter(nameFilters[selectedFilter])

    if dialog.exec_() != QDialog.Accepted:
        return None

    filename = dialog.selectedFiles()[0]
    if fileMode != QFileDialog.Directory:
        selectedFilter = nameFilters.index(dialog.selectedNameFilter())

        _, ext = os.path.splitext(filename)

        if not ext:
            ext = filters[selectedFilter][1]  # use first extension
            if ext.startswith('*.') and ext != '*.*':
                return filename + ext[1:]  # remove leading '*'
    return filename
Exemple #17
0
def _fileDialog(acceptMode, fileMode,
                parent=None, caption='', directory='', filters=(),
                selectedFilter=None, options=0):

    nameFilters = make_filters(filters)

    dialog = QFileDialog(parent, caption, directory)
    dialog.setNameFilters(nameFilters)
    dialog.setAcceptMode(acceptMode)
    dialog.setFileMode(fileMode)
    dialog.setOptions(QFileDialog.Options(options))
    if selectedFilter is not None:
        dialog.selectNameFilter(nameFilters[selectedFilter])

    if dialog.exec_() != QDialog.Accepted:
        return None

    filename = dialog.selectedFiles()[0]
    if fileMode != QFileDialog.Directory:
        selectedFilter = nameFilters.index(dialog.selectedNameFilter())

        _, ext = os.path.splitext(filename)

        if not ext:
            ext = filters[selectedFilter][1]    # use first extension
            if ext.startswith('*.') and ext != '*.*':
                return filename + ext[1:]       # remove leading '*'
    return filename
Exemple #18
0
def file_dialog(dir='', for_open=True, fmt='', is_folder=False):
    """Dialog z eksploratorem Windows. Otwieranie/tworzenie folderów i plików."""
    options = QFileDialog.Options()
    options |= QFileDialog.DontUseNativeDialog
    options |= QFileDialog.DontUseCustomDirectoryIcons
    dialog = QFileDialog()
    dialog.setOptions(options)
    dialog.setFilter(dialog.filter() | QDir.Hidden)
    if is_folder:  # Otwieranie folderu
        dialog.setFileMode(QFileDialog.DirectoryOnly)
    else:  # Otwieranie pliku
        dialog.setFileMode(QFileDialog.AnyFile)
    # Otwieranie / zapisywanie:
    dialog.setAcceptMode(
        QFileDialog.AcceptOpen) if for_open else dialog.setAcceptMode(
            QFileDialog.AcceptSave)
    # Ustawienie filtrowania rozszerzeń plików:
    if fmt != '' and not is_folder:
        dialog.setDefaultSuffix(fmt)
        dialog.setNameFilters([f'{fmt} (*.{fmt})'])
    # Ścieżka startowa:
    if dir != '':
        dialog.setDirectory(str(dir))
    else:
        dialog.setDirectory(str(os.environ["HOMEPATH"]))
    # Przekazanie ścieżki folderu/pliku:
    if dialog.exec_() == QDialog.Accepted:
        path = dialog.selectedFiles()[0]
        return path
    else:
        return ''
Exemple #19
0
def show_files_request(qt_widget, title, root_path):
    opts = QFileDialog.DontUseNativeDialog
    dialog = QFileDialog()
    dialog.setWindowTitle(title)
    dialog.setViewMode(QFileDialog.List)
    dialog.setOptions(opts)
    filenames = dialog.getOpenFileNames(qt_widget, title, root_path)
    return filenames[0]
Exemple #20
0
def saveDialog(name, filter):
    """ Create non-native save file dialog. """
    qfd = QFileDialog(getWindow(), name)
    qfd.setNameFilter(filter)
    qfd.setFileMode(QFileDialog.AnyFile)
    qfd.setOptions(QFileDialog.DontUseNativeDialog)
    qfd.setAcceptMode(QFileDialog.AcceptSave)
    qfd.setViewMode(QFileDialog.List)
    return qfd
Exemple #21
0
def openDialog(name, filter):
    """ Create non-native open file dialog. """
    qfd = QFileDialog(getWindow(), name)
    qfd.setNameFilter(filter)
    qfd.setFileMode(QFileDialog.ExistingFile)
    qfd.setOptions(QFileDialog.DontUseNativeDialog)
    qfd.setAcceptMode(QFileDialog.AcceptOpen)
    qfd.setViewMode(QFileDialog.List)
    return qfd
Exemple #22
0
 def write_cfg(self):
   dialog = QFileDialog(self, 'Write configuration settings', '.', '*.ini')
   dialog.setDefaultSuffix('ini')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     settings = QSettings(name[0], QSettings.IniFormat)
     self.write_cfg_settings(settings)
Exemple #23
0
 def action_select_output_files_path(self):
     options = QFileDialog.Options()
     options |= QFileDialog.DontUseNativeDialog
     options |= QFileDialog.DontUseCustomDirectoryIcons
     dialog = QFileDialog()
     dialog.setOptions(options)
     dialog.setFilter(dialog.filter() | QDir.Hidden)
     path  = dialog.getExistingDirectory(self, 'Select directory', options=options)
     if path:
         self.lineedit_output_files_path.setText(path)
Exemple #24
0
def set_edii_path(config):
    dlg = QFileDialog(None, 'Set path to EDII service',
                      config.get_value('edii_path'))
    dlg.setAcceptMode(QFileDialog.AcceptOpen)
    dlg.setOptions(QFileDialog.ShowDirsOnly | QFileDialog.ReadOnly)

    ret = dlg.exec_()
    if ret != QDialog.Accepted:
        return

    config.set_value('edii_path', dlg.selectedFiles()[0])
Exemple #25
0
    def GetIconPath(self):
        from PyQt5.QtWidgets import QFileDialog, QDialog

        opt = QtWidgets.QFileDialog.Options()
        opt |= QtWidgets.QFileDialog.DontUseSheet
        dialog = QFileDialog()
        dialog.setOptions(opt)
        dialog.setDirectory(self.appPath)
        path = QtWidgets.QFileDialog.getExistingDirectory(
            None, "Default Icon Directory...", self.appPath, options=opt)
        if path:
            self.IconPath.setText(path)
def create_file_dialog():
    """
    Create a file dialog object, ready to use
    :return:
    """
    dialog = QFileDialog()
    dialog.setFileMode(QFileDialog.DirectoryOnly)
    options = QFileDialog.Options()
    options |= QFileDialog.DontUseNativeDialog
    options |= QFileDialog.ShowDirsOnly
    dialog.setOptions(options)
    return dialog
 def _open(self):
     proxy_model = ExecutableFilterModel()
     options = QFileDialog.Options()
     options |= QFileDialog.DontUseNativeDialog
     dialog = QFileDialog(self.widget, "Select a source port",
                          self.config.get("sourcePortDir"))
     dialog.setOptions(options)
     dialog.setProxyModel(proxy_model)
     if dialog.exec_() == QDialog.Accepted:
         filename = dialog.selectedUrls()[0].toLocalFile()
         self.saveSourcePortPath(filename)
         self.setSourcePort(filename)
Exemple #28
0
 def _openProject(self):
     dialog = QFileDialog(self)
     dialog.setFileMode(QFileDialog.DirectoryOnly)
     dialog.setOptions(QFileDialog.ShowDirsOnly)
     if dialog.exec():
         # TODO: this returns a list... should give user an error if they select multiple
         dir = dialog.selectedFiles()[0]
         self._tree = builder.build(root=dir)
         for doc in self._tree:
             self._docTree.addItem(doc)
             self._reqStack.addDoc(doc)
             self._reqView.addDoc(doc)
         self.mainContainer.show()
Exemple #29
0
 def selectFile(self, label):
     fd = QFileDialog()
     fd.setWindowTitle('Open ' + label + ' File')
     fd.setLabelText(QFileDialog.Accept, "Select " + label)
     fd.setNameFilters(["Fits Files (*.fit* *.FIT*)"])
     fd.setOptions(QFileDialog.DontUseNativeDialog)
     fd.setViewMode(QFileDialog.List)
     if (fd.exec()):
         fileNames = fd.selectedFiles()
         return fileNames[0]
     else:
         return None
         print("No file selected")
Exemple #30
0
 def write_s2p(self, gain):
   dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p')
   dialog.setDefaultSuffix('s2p')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     fh = open(name[0], 'w')
     freq = self.dut.freq
     gamma = self.gamma(freq)
     fh.write('# GHz S MA R 50\n')
     for i in range(freq.size):
       fh.write('0.0%.8d   %8.6f %7.2f   %8.6f %7.2f   0.000000    0.00   0.000000    0.00\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True)))
     fh.close()
Exemple #31
0
 def write_s1p(self):
   dialog = QFileDialog(self, 'Write s1p file', '.', '*.s1p')
   dialog.setDefaultSuffix('s1p')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     fh = open(name[0], 'w')
     gamma = self.gamma()
     size = self.sizeValue.value()
     fh.write('# GHz S MA R 50\n')
     for i in range(0, size):
       fh.write('0.0%.8d   %8.6f %7.2f\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True)))
     fh.close()
Exemple #32
0
 def write_csv(self):
   dialog = QFileDialog(self, 'Write csv file', '.', '*.csv')
   dialog.setDefaultSuffix('csv')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     fh = open(name[0], 'w')
     gamma = self.gamma()
     size = self.sizeValue.value()
     fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n')
     for i in range(0, size):
       fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (self.xaxis[i], self.open.real[i], self.open.imag[i], self.short.real[i], self.short.imag[i], self.load.real[i], self.load.imag[i], self.dut.real[i], self.dut.imag[i]))
     fh.close()
Exemple #33
0
 def write_s2p(self, gain):
   dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p')
   dialog.setDefaultSuffix('s2p')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     fh = open(name[0], 'w')
     freq = self.dut.freq
     gamma = self.gamma(freq)
     fh.write('# GHz S MA R 50\n')
     for i in range(freq.size):
       fh.write('0.0%.8d   %8.6f %7.2f   %8.6f %7.2f   0.000000    0.00   0.000000    0.00\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True)))
     fh.close()
Exemple #34
0
 def write_csv(self):
   dialog = QFileDialog(self, 'Write csv file', '.', '*.csv')
   dialog.setDefaultSuffix('csv')
   dialog.setAcceptMode(QFileDialog.AcceptSave)
   dialog.setOptions(QFileDialog.DontConfirmOverwrite)
   if dialog.exec() == QDialog.Accepted:
     name = dialog.selectedFiles()
     fh = open(name[0], 'w')
     f = self.dut.freq
     o = self.interp(f, self.open)
     s = self.interp(f, self.short)
     l = self.interp(f, self.load)
     d = self.dut.data
     fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n')
     for i in range(f.size):
       fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (f[i] * 1000, o.real[i], o.imag[i], s.real[i], s.imag[i], l.real[i], l.imag[i], d.real[i], d.imag[i]))
     fh.close()
Exemple #35
0
 def _get_save_file_name(self, file_format):
     if file_format == export.FileFormat.XLSX:
         file_filter = FileNameFilters.xlsx_file
         extension = 'xlsx'
     else:
         file_filter = FileNameFilters.csv_file
         extension = 'csv'
     save_dialog = QFileDialog(parent=self, caption=_('Save listing as...'),
                               filter=file_filter)
     save_dialog.setOptions(QFileDialog.DontUseNativeDialog)
     save_dialog.setDefaultSuffix(extension)
     save_dialog.setFileMode(QFileDialog.AnyFile)
     save_dialog.setAcceptMode(QFileDialog.AcceptSave)
     filename = None
     if save_dialog.exec_():
         filename_list = save_dialog.selectedFiles()
         if len(filename_list) == 1:
             filename = filename_list[0]
     return filename
Exemple #36
0
    def dialog_export_exam_config(self):
        """Displays the dialog for exporting the current exam configuration.

        If accepted by the user, it returns the filename.
        Returns None if cancelled.

        """
        save_dialog = QFileDialog(parent=self.window,
                                  caption=_('Save exam configration as...'),
                                  filter=_('Exam configuration (*.eye)'))
        save_dialog.setOptions(QFileDialog.DontUseNativeDialog)
        save_dialog.setDefaultSuffix('eye')
        save_dialog.setFileMode(QFileDialog.AnyFile)
        save_dialog.setAcceptMode(QFileDialog.AcceptSave)
        filename = None
        if save_dialog.exec_():
            filename_list = save_dialog.selectedFiles()
            if len(filename_list) == 1:
                filename = filename_list[0]
        return filename
Exemple #37
0
def get_open_dialog(directory_mode=False, parent=None, name_filter="full") -> QFileDialog:
    fip = FileIconProvider()
    dialog = QFileDialog(parent=parent, directory=RECENT_PATH)
    dialog.setIconProvider(fip)

    if directory_mode:
        dialog.setFileMode(QFileDialog.Directory)
        dialog.setWindowTitle("Open Folder")
    else:
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setWindowTitle("Open Files")
        if name_filter == "full":
            name_filter = "All Files (*);;" \
                          "Complex (*.complex);;" \
                          "Complex16 unsigned (*.complex16u *.cu8);;" \
                          "Complex16 signed (*.complex16s *.cs8);;" \
                          "WAV (*.wav);;" \
                          "Protocols (*.proto.xml *.proto);;" \
                          "Binary Protocols (*.bin);;" \
                          "Fuzzing Profiles (*.fuzz.xml *.fuzz);;" \
                          "Simulator (*.sim.xml *.sim)" \
                          "Plain Bits (*.txt);;" \
                          "Tar Archives (*.tar *.tar.gz *.tar.bz2);;" \
                          "Zip Archives (*.zip)"
        elif name_filter == "proto":
            name_filter = "Protocols (*.proto.xml *.proto);; Binary Protocols (*.bin)"
        elif name_filter == "fuzz":
            name_filter = "Fuzzprofiles (*.fuzz.xml *.fuzz)"
        elif name_filter == "simulator":
            name_filter = "Simulator (*.sim.xml *.sim)"

        dialog.setNameFilter(name_filter)

    dialog.setOptions(QFileDialog.DontResolveSymlinks)
    dialog.setViewMode(QFileDialog.Detail)

    return dialog
    def browse(self):
        """
        Open a file dialog and select a user specified file.
        """
        formats = [
            "Text - comma separated (*.csv, *)",
            "Text - tab separated (*.tsv, *)",
            "Text - all files (*)"
        ]

        dlg = QFileDialog(
            self, windowTitle="Open Data File",
            acceptMode=QFileDialog.AcceptOpen,
            fileMode=QFileDialog.ExistingFile
        )
        dlg.setNameFilters(formats)
        state = self.dialog_state
        lastdir = state.get("directory", "")
        lastfilter = state.get("filter", "")

        if lastdir and os.path.isdir(lastdir):
            dlg.setDirectory(lastdir)
        if lastfilter:
            dlg.selectNameFilter(lastfilter)

        status = dlg.exec_()
        dlg.deleteLater()
        if status == QFileDialog.Accepted:
            self.dialog_state["directory"] = dlg.directory().absolutePath()
            self.dialog_state["filter"] = dlg.selectedNameFilter()

            selected_filter = dlg.selectedNameFilter()
            path = dlg.selectedFiles()[0]
            # pre-flight check; try to determine the nature of the file
            mtype = _mime_type_for_path(path)
            if not mtype.inherits("text/plain"):
                mb = QMessageBox(
                    parent=self,
                    windowTitle="",
                    icon=QMessageBox.Question,
                    text="The '{basename}' may be a binary file.\n"
                         "Are you sure you want to continue?".format(
                            basename=os.path.basename(path)),
                    standardButtons=QMessageBox.Cancel | QMessageBox.Yes
                )
                mb.setWindowModality(Qt.WindowModal)
                if mb.exec() == QMessageBox.Cancel:
                    return

            # initialize dialect based on selected extension
            if selected_filter in formats[:-1]:
                filter_idx = formats.index(selected_filter)
                if filter_idx == 0:
                    dialect = csv.excel()
                elif filter_idx == 1:
                    dialect = csv.excel_tab()
                else:
                    dialect = csv.excel_tab()
                header = True
            else:
                try:
                    dialect, header = sniff_csv_with_path(path)
                except Exception:
                    dialect, header = csv.excel(), True

            options = None
            # Search for path in history.
            # If found use the stored params to initialize the import dialog
            items = self.itemsFromSettings()
            idx = index_where(items, lambda t: samepath(t[0], path))
            if idx is not None:
                _, options_ = items[idx]
                if options_ is not None:
                    options = options_

            if options is None:
                if not header:
                    rowspec = []
                else:
                    rowspec = [(range(0, 1), RowSpec.Header)]
                options = Options(
                    encoding="utf-8", dialect=dialect, rowspec=rowspec)

            dlg = CSVImportDialog(
                self, windowTitle="Import Options",  sizeGripEnabled=True)
            dlg.setWindowModality(Qt.WindowModal)
            dlg.setPath(path)
            dlg.setOptions(options)
            status = dlg.exec_()
            dlg.deleteLater()
            if status == QDialog.Accepted:
                self.set_selected_file(path, dlg.options())
Exemple #39
0
class MainController(QMainWindow):
    def __init__(self, *args):
        super().__init__(*args)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        OptionsController.write_default_options()

        self.project_save_timer = QTimer()
        self.project_manager = ProjectManager(self)
        self.plugin_manager = PluginManager()
        self.signal_tab_controller = SignalTabController(self.project_manager,
                                                         parent=self.ui.tab_interpretation)
        self.ui.tab_interpretation.layout().addWidget(self.signal_tab_controller)
        self.compare_frame_controller = CompareFrameController(parent=self.ui.tab_protocol,
                                                               plugin_manager=self.plugin_manager,
                                                               project_manager=self.project_manager)
        self.compare_frame_controller.ui.splitter.setSizes([1, 1000000])


        self.ui.tab_protocol.layout().addWidget(self.compare_frame_controller)

        self.generator_tab_controller = GeneratorTabController(self.compare_frame_controller,
                                                               self.project_manager,
                                                               parent=self.ui.tab_generator)

        self.undo_group = QUndoGroup()
        self.undo_group.addStack(self.signal_tab_controller.signal_undo_stack)
        self.undo_group.addStack(self.compare_frame_controller.protocol_undo_stack)
        self.undo_group.addStack(self.generator_tab_controller.generator_undo_stack)
        self.undo_group.setActiveStack(self.signal_tab_controller.signal_undo_stack)

        self.participant_legend_model = ParticipantLegendListModel(self.project_manager.participants)
        self.ui.listViewParticipants.setModel(self.participant_legend_model)

        gtc = self.generator_tab_controller
        gtc.ui.splitter.setSizes([gtc.width() / 0.7, gtc.width() / 0.3])

        self.ui.tab_generator.layout().addWidget(self.generator_tab_controller)

        self.signal_protocol_dict = {}  # type: dict[SignalFrameController, ProtocolAnalyzer]

        self.ui.lnEdtTreeFilter.setClearButtonEnabled(True)

        group = QActionGroup(self)
        self.ui.actionFSK.setActionGroup(group)
        self.ui.actionOOK.setActionGroup(group)
        self.ui.actionNone.setActionGroup(group)
        self.ui.actionPSK.setActionGroup(group)

        self.recentFileActionList = []
        self.create_connects()
        self.init_recent_file_action_list(constants.SETTINGS.value("recentFiles", []))

        self.filemodel = FileSystemModel(self)
        path = QDir.homePath()

        self.filemodel.setIconProvider(FileIconProvider())
        self.filemodel.setRootPath(path)
        self.file_proxy_model = FileFilterProxyModel(self)
        self.file_proxy_model.setSourceModel(self.filemodel)
        self.ui.fileTree.setModel(self.file_proxy_model)

        self.ui.fileTree.setRootIndex(self.file_proxy_model.mapFromSource(self.filemodel.index(path)))
        self.ui.fileTree.setToolTip(path)
        self.ui.fileTree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.ui.fileTree.header().setSectionResizeMode(1, QHeaderView.Stretch)
        self.ui.fileTree.setFocus()

        self.generator_tab_controller.table_model.cfc = self.compare_frame_controller

        self.ui.actionConvert_Folder_to_Project.setEnabled(False)

        undo_action = self.undo_group.createUndoAction(self)
        undo_action.setIcon(QIcon.fromTheme("edit-undo"))
        undo_action.setShortcut(QKeySequence.Undo)
        self.ui.menuEdit.insertAction(self.ui.actionDecoding, undo_action)

        redo_action = self.undo_group.createRedoAction(self)
        redo_action.setIcon(QIcon.fromTheme("edit-redo"))
        redo_action.setShortcut(QKeySequence.Redo)
        self.ui.menuEdit.insertAction(self.ui.actionDecoding, redo_action)
        self.ui.menuEdit.insertSeparator(self.ui.actionDecoding)

        self.ui.actionAbout_Qt.setIcon(QIcon(":/qt-project.org/qmessagebox/images/qtlogo-64.png"))

        self.ui.splitter.setSizes([0, 1])
        self.refresh_main_menu()

        self.apply_default_view(constants.SETTINGS.value('default_view', type=int))
        self.project_save_timer.start(ProjectManager.AUTOSAVE_INTERVAL_MINUTES * 60 * 1000)

        self.ui.actionProject_settings.setVisible(False)
        self.ui.actionSave_project.setVisible(False)

    def create_connects(self):
        self.ui.actionFullscreen_mode.setShortcut(QKeySequence.FullScreen)
        self.ui.actionOpen.setShortcut(QKeySequence(QKeySequence.Open))
        self.ui.actionOpen_directory.setShortcut(QKeySequence("Ctrl+Shift+O"))

        self.ui.menuEdit.aboutToShow.connect(self.on_edit_menu_about_to_show)

        self.ui.actionNew_Project.triggered.connect(self.on_new_project_action_triggered)
        self.ui.actionNew_Project.setShortcut(QKeySequence.New)
        self.ui.actionProject_settings.triggered.connect(self.on_project_settings_action_triggered)
        self.ui.actionSave_project.triggered.connect(self.project_manager.saveProject)

        self.ui.actionAbout_AutomaticHacker.triggered.connect(self.on_show_about_clicked)
        self.ui.actionRecord.triggered.connect(self.on_show_record_dialog_action_triggered)

        self.ui.actionFullscreen_mode.triggered.connect(self.on_fullscreen_action_triggered)
        self.ui.actionSaveAllSignals.triggered.connect(self.signal_tab_controller.save_all)
        self.ui.actionClose_all.triggered.connect(self.on_close_all_action_triggered)
        self.ui.actionOpen.triggered.connect(self.on_open_file_action_triggered)
        self.ui.actionOpen_directory.triggered.connect(self.on_open_directory_action_triggered)
        self.ui.actionDecoding.triggered.connect(self.on_show_decoding_dialog_triggered)
        self.ui.actionSpectrum_Analyzer.triggered.connect(self.on_show_spectrum_dialog_action_triggered)
        self.ui.actionOptions.triggered.connect(self.show_options_dialog_action_triggered)
        self.ui.actionSniff_protocol.triggered.connect(self.show_proto_sniff_dialog)
        self.ui.actionAbout_Qt.triggered.connect(QApplication.instance().aboutQt)

        self.ui.btnFileTreeGoUp.clicked.connect(self.on_btn_file_tree_go_up_clicked)
        self.ui.fileTree.directory_open_wanted.connect(self.project_manager.set_project_folder)

        self.signal_tab_controller.frame_closed.connect(self.close_signal_frame)
        self.signal_tab_controller.signal_created.connect(self.add_signal)
        self.signal_tab_controller.ui.scrollArea.files_dropped.connect(self.on_files_dropped)
        self.signal_tab_controller.files_dropped.connect(self.on_files_dropped)
        self.signal_tab_controller.frame_was_dropped.connect(self.set_frame_numbers)

        self.compare_frame_controller.show_interpretation_clicked.connect(
            self.show_protocol_selection_in_interpretation)
        self.compare_frame_controller.files_dropped.connect(self.on_files_dropped)
        self.compare_frame_controller.show_decoding_clicked.connect(self.on_show_decoding_dialog_triggered)
        self.compare_frame_controller.ui.treeViewProtocols.files_dropped_on_group.connect(
            self.on_files_dropped_on_group)
        self.compare_frame_controller.participant_changed.connect(self.signal_tab_controller.on_participant_changed)
        self.compare_frame_controller.ui.treeViewProtocols.close_wanted.connect(self.on_cfc_close_wanted)
        self.compare_frame_controller.show_config_field_types_triggered.connect(
            self.on_show_field_types_config_action_triggered)

        self.ui.lnEdtTreeFilter.textChanged.connect(self.on_file_tree_filter_text_changed)

        self.ui.tabWidget.currentChanged.connect(self.on_selected_tab_changed)
        self.project_save_timer.timeout.connect(self.project_manager.saveProject)

        self.ui.actionConvert_Folder_to_Project.triggered.connect(self.project_manager.convert_folder_to_project)
        self.project_manager.project_loaded_status_changed.connect(self.ui.actionProject_settings.setVisible)
        self.project_manager.project_loaded_status_changed.connect(self.ui.actionSave_project.setVisible)
        self.project_manager.project_loaded_status_changed.connect(self.ui.actionConvert_Folder_to_Project.setDisabled)
        self.project_manager.project_updated.connect(self.on_project_updated)

        self.ui.textEditProjectDescription.textChanged.connect(self.on_text_edit_project_description_text_changed)
        self.ui.tabWidget_Project.tabBarDoubleClicked.connect(self.on_project_tab_bar_double_clicked)

        self.ui.listViewParticipants.doubleClicked.connect(self.on_project_settings_action_triggered)

        self.ui.actionShowFileTree.triggered.connect(self.on_action_show_filetree_triggered)
        self.ui.actionShowFileTree.setShortcut(QKeySequence("F10"))

        self.ui.menuFile.addSeparator()
        for i in range(constants.MAX_RECENT_FILE_NR):
            recent_file_action = QAction(self)
            recent_file_action.setVisible(False)
            recent_file_action.triggered.connect(self.on_open_recent_action_triggered)
            self.recentFileActionList.append(recent_file_action)
            self.ui.menuFile.addAction(self.recentFileActionList[i])

    def add_plain_bits_from_txt(self, filename: str):
        protocol = ProtocolAnalyzer(None)
        protocol.filename = filename
        with open(filename) as f:
            for line in f:
                protocol.messages.append(Message.from_plain_bits_str(line.strip()))

        self.compare_frame_controller.add_protocol(protocol)
        self.compare_frame_controller.refresh()
        self.__add_empty_frame_for_filename(protocol, filename)

    def __add_empty_frame_for_filename(self, protocol: ProtocolAnalyzer, filename: str):
        sf = self.signal_tab_controller.add_empty_frame(filename, protocol)
        self.signal_protocol_dict[sf] = protocol
        self.set_frame_numbers()
        self.file_proxy_model.open_files.add(filename)

    def add_protocol_file(self, filename):
        proto = self.compare_frame_controller.add_protocol_from_file(filename)
        if proto:
            self.__add_empty_frame_for_filename(proto, filename)

    def add_fuzz_profile(self, filename):
        self.ui.tabWidget.setCurrentIndex(2)
        self.generator_tab_controller.load_from_file(filename)

    def add_signalfile(self, filename: str, group_id=0):
        if not os.path.exists(filename):
            QMessageBox.critical(self, self.tr("File not Found"),
                                 self.tr("The file {0} could not be found. Was it moved or renamed?").format(
                                     filename))
            return

        already_qad_demodulated = False
        if filename.endswith(".wav"):
            cb = QCheckBox("Signal in file is already quadrature demodulated")
            msg = self.tr("You selected a .wav file as signal.\n"
                          "Universal Radio Hacker (URH) will interpret it as real part of the signal.\n"
                          "Protocol results may be bad due to missing imaginary part.\n\n"
                          "Load a complex file if you experience problems.\n"
                          "You have been warned.")
            msg_box = QMessageBox(QMessageBox.Information, "WAV file selected", msg)
            msg_box.addButton(QMessageBox.Ok)
            msg_box.addButton(QMessageBox.Abort)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            if reply != QMessageBox.Ok:
                return

            already_qad_demodulated = cb.isChecked()

        sig_name = os.path.splitext(os.path.basename(filename))[0]

        # Use default sample rate for signal
        # Sample rate will be overriden in case of a project later
        signal = Signal(filename, sig_name, wav_is_qad_demod=already_qad_demodulated,
                        sample_rate=self.project_manager.device_conf["sample_rate"])

        if self.project_manager.project_file is None:
            self.adjust_for_current_file(signal.filename)

        self.file_proxy_model.open_files.add(filename)
        self.add_signal(signal, group_id)

    def add_signal(self, signal, group_id=0):
        self.setCursor(Qt.WaitCursor)
        pa = ProtocolAnalyzer(signal)
        sig_frame = self.signal_tab_controller.add_signal_frame(pa)
        pa = self.compare_frame_controller.add_protocol(pa, group_id)

        signal.blockSignals(True)
        has_entry = self.project_manager.read_project_file_for_signal(signal)
        if not has_entry:
            signal.auto_detect()
        signal.blockSignals(False)

        self.signal_protocol_dict[sig_frame] = pa

        sig_frame.refresh(draw_full_signal=True)  # Hier wird das Protokoll ausgelesen
        if self.project_manager.read_participants_for_signal(signal, pa.messages):
            sig_frame.ui.gvSignal.redraw_view()

        sig_frame.ui.gvSignal.auto_fit_view()
        self.set_frame_numbers()

        self.compare_frame_controller.filter_search_results()
        self.refresh_main_menu()
        self.unsetCursor()

    def close_protocol(self, protocol):
        self.compare_frame_controller.remove_protocol(protocol)
        # Needs to be removed in generator also, otherwise program crashes,
        # if item from tree in generator is selected and corresponding signal is closed
        self.generator_tab_controller.tree_model.remove_protocol(protocol)
        protocol.eliminate()

    def close_signal_frame(self, signal_frame: SignalFrameController):
        try:
            self.project_manager.write_signal_information_to_project_file(signal_frame.signal)
            try:
                proto = self.signal_protocol_dict[signal_frame]
            except KeyError:
                proto = None

            if proto is not None:
                self.close_protocol(proto)
                del self.signal_protocol_dict[signal_frame]

            if self.signal_tab_controller.ui.scrlAreaSignals.minimumHeight() > signal_frame.height():
                self.signal_tab_controller.ui.scrlAreaSignals.setMinimumHeight(
                    self.signal_tab_controller.ui.scrlAreaSignals.minimumHeight() - signal_frame.height())

            if signal_frame.signal is not None:
                # Non-Empty Frame (when a signal and not a protocol is opened)
                self.file_proxy_model.open_files.discard(signal_frame.signal.filename)

            signal_frame.eliminate()

            self.compare_frame_controller.ui.treeViewProtocols.expandAll()
            self.set_frame_numbers()
            self.refresh_main_menu()
        except Exception as e:
            Errors.generic_error(self.tr("Failed to close"), str(e), traceback.format_exc())
            self.unsetCursor()

    def add_files(self, filepaths, group_id=0):
        num_files = len(filepaths)
        if num_files == 0:
            return

        for i, file in enumerate(filepaths):
            if not os.path.exists(file):
                continue

            if os.path.isdir(file):
                for f in self.signal_tab_controller.signal_frames:
                    self.close_signal_frame(f)

                FileOperator.RECENT_PATH = file
                self.project_manager.set_project_folder(file)
                return

            _, file_extension = os.path.splitext(file)
            FileOperator.RECENT_PATH = os.path.split(file)[0]

            if file_extension == ".complex":
                self.add_signalfile(file, group_id)
            elif file_extension == ".coco":
                self.add_signalfile(file, group_id)
            elif file_extension == ".proto":
                self.add_protocol_file(file)
            elif file_extension == ".wav":
                self.add_signalfile(file, group_id)
            elif file_extension == ".fuzz":
                self.add_fuzz_profile(file)
            elif file_extension == ".txt":
                self.add_plain_bits_from_txt(file)
            else:
                self.add_signalfile(file, group_id)

    def set_frame_numbers(self):
        self.signal_tab_controller.set_frame_numbers()

    def closeEvent(self, event: QCloseEvent):
        self.project_manager.saveProject()
        super().closeEvent(event)

    def close_all(self):

        self.filemodel.setRootPath(QDir.homePath())
        self.ui.fileTree.setRootIndex(self.file_proxy_model.mapFromSource(self.filemodel.index(QDir.homePath())))
        self.project_manager.saveProject()

        self.signal_tab_controller.close_all()
        self.compare_frame_controller.reset()
        self.generator_tab_controller.table_model.protocol.clear()
        self.generator_tab_controller.refresh_tree()
        self.generator_tab_controller.refresh_table()
        self.generator_tab_controller.refresh_label_list()

        self.project_manager.project_path = ""
        self.project_manager.project_file = None
        self.signal_tab_controller.signal_undo_stack.clear()
        self.compare_frame_controller.protocol_undo_stack.clear()
        self.generator_tab_controller.generator_undo_stack.clear()

    def show_options_dialog_specific_tab(self, tab_index: int):
        op = OptionsController(self.plugin_manager.installed_plugins, parent=self)
        op.values_changed.connect(self.on_options_changed)
        op.ui.tabWidget.setCurrentIndex(tab_index)
        op.show()

    def refresh_main_menu(self):
        enable = len(self.signal_protocol_dict) > 0
        self.ui.actionSaveAllSignals.setEnabled(enable)
        self.ui.actionClose_all.setEnabled(enable)

    def apply_default_view(self, view_index: int):
        self.compare_frame_controller.ui.cbProtoView.setCurrentIndex(view_index)
        self.generator_tab_controller.ui.cbViewType.setCurrentIndex(view_index)
        for sig_frame in self.signal_tab_controller.signal_frames:
            sig_frame.ui.cbProtoView.setCurrentIndex(view_index)

    def show_project_settings(self):
        pdc = ProjectDialogController(new_project=False, project_manager=self.project_manager, parent=self)
        pdc.finished.connect(self.on_project_dialog_finished)
        pdc.show()

    def collapse_project_tab_bar(self):
        self.ui.tabParticipants.hide()
        self.ui.tabDescription.hide()
        self.ui.tabWidget_Project.setMaximumHeight(self.ui.tabWidget_Project.tabBar().height())

    def expand_project_tab_bar(self):
        self.ui.tabDescription.show()
        self.ui.tabParticipants.show()
        self.ui.tabWidget_Project.setMaximumHeight(9000)

    @pyqtSlot()
    def on_project_tab_bar_double_clicked(self):
        if self.ui.tabParticipants.isVisible():
            self.collapse_project_tab_bar()
        else:
            self.expand_project_tab_bar()

    @pyqtSlot()
    def on_project_updated(self):
        self.participant_legend_model.participants = self.project_manager.participants
        self.participant_legend_model.update()
        self.compare_frame_controller.refresh()
        self.ui.textEditProjectDescription.setText(self.project_manager.description)

    @pyqtSlot()
    def on_fullscreen_action_triggered(self):
        if self.ui.actionFullscreen_mode.isChecked():
            self.showFullScreen()
        else:
            self.showMaximized()

    @pyqtSlot(str)
    def adjust_for_current_file(self, file_path):
        if file_path is None:
            return

        if file_path in FileOperator.archives.keys():
            file_path = copy.copy(FileOperator.archives[file_path])

        settings = constants.SETTINGS
        recent_file_paths = settings.value("recentFiles", [])
        recent_file_paths = [] if recent_file_paths is None else recent_file_paths  # check None for OSX
        recent_file_paths = [p for p in recent_file_paths if p != file_path and p is not None and os.path.exists(p)]
        recent_file_paths.insert(0, file_path)
        recent_file_paths = recent_file_paths[:constants.MAX_RECENT_FILE_NR]

        self.init_recent_file_action_list(recent_file_paths)

        settings.setValue("recentFiles", recent_file_paths)

    def init_recent_file_action_list(self, recent_file_paths: list):
        for i in range(len(self.recentFileActionList)):
            self.recentFileActionList[i].setVisible(False)

        if recent_file_paths is None:
            return

        for i, file_path in enumerate(recent_file_paths):
            if os.path.isfile(file_path):
                display_text = os.path.basename(file_path)
                self.recentFileActionList[i].setIcon(QIcon())
            elif os.path.isdir(file_path):
                head, tail = os.path.split(file_path)
                display_text = tail
                head, tail = os.path.split(head)
                if tail:
                    display_text = tail + "/" + display_text

                self.recentFileActionList[i].setIcon(QIcon.fromTheme("folder"))
            else:
                continue

            self.recentFileActionList[i].setText(display_text)
            self.recentFileActionList[i].setData(file_path)
            self.recentFileActionList[i].setVisible(True)

    @pyqtSlot()
    def on_show_field_types_config_action_triggered(self):
        self.show_options_dialog_specific_tab(tab_index=2)

    @pyqtSlot()
    def on_open_recent_action_triggered(self):
        action = self.sender()
        try:
            if os.path.isdir(action.data()):
                self.project_manager.set_project_folder(action.data())
            elif os.path.isfile(action.data()):
                self.setCursor(Qt.WaitCursor)
                self.add_files(FileOperator.uncompress_archives([action.data()], QDir.tempPath()))
                self.unsetCursor()
        except Exception as e:
            Errors.generic_error(self.tr("Failed to open"), str(e), traceback.format_exc())
            self.unsetCursor()

    @pyqtSlot()
    def on_show_about_clicked(self):
        descr = "<b><h2>Universal Radio Hacker</h2></b>Version: {0}<br />" \
                "GitHub: <a href='https://github.com/jopohl/urh'>https://github.com/jopohl/urh</a><br /><br />" \
                "Creators:<i><ul><li>" \
                "Johannes Pohl &lt;<a href='mailto:[email protected]'>[email protected]</a>&gt;</li>" \
                "<li>Andreas Noack &lt;<a href='mailto:[email protected]'>[email protected]</a>&gt;</li>" \
                "</ul></i>".format(version.VERSION)

        QMessageBox.about(self, self.tr("About"), self.tr(descr))

    @pyqtSlot(int, int, int, int)
    def show_protocol_selection_in_interpretation(self, start_message, start, end_message, end):
        cfc = self.compare_frame_controller
        msg_total = 0
        last_sig_frame = None
        for protocol in cfc.protocol_list:
            if not protocol.show:
                continue
            n = protocol.num_messages
            view_type = cfc.ui.cbProtoView.currentIndex()
            messages = [i - msg_total for i in range(msg_total, msg_total + n) if start_message <= i <= end_message]
            if len(messages) > 0:
                try:
                    signal_frame = next((sf for sf, pf in self.signal_protocol_dict.items() if pf == protocol))
                except StopIteration:
                    QMessageBox.critical(self, self.tr("Error"),
                                         self.tr("Could not find corresponding signal frame."))
                    return
                signal_frame.set_roi_from_protocol_analysis(min(messages), start, max(messages), end + 1, view_type)
                last_sig_frame = signal_frame
            msg_total += n
        focus_frame = last_sig_frame
        if last_sig_frame is not None:
            self.signal_tab_controller.ui.scrollArea.ensureWidgetVisible(last_sig_frame, 0, 0)

        QApplication.instance().processEvents()
        self.ui.tabWidget.setCurrentIndex(0)
        if focus_frame is not None:
            focus_frame.ui.txtEdProto.setFocus()

    @pyqtSlot(str)
    def on_file_tree_filter_text_changed(self, text: str):
        if len(text) > 0:
            self.filemodel.setNameFilters(["*" + text + "*"])
        else:
            self.filemodel.setNameFilters(["*"])

    @pyqtSlot()
    def on_show_decoding_dialog_triggered(self):
        signals = [sf.signal for sf in self.signal_tab_controller.signal_frames]
        decoding_controller = DecoderWidgetController(
            self.compare_frame_controller.decodings, signals,
            self.project_manager, parent=self)
        decoding_controller.finished.connect(self.update_decodings)
        decoding_controller.show()
        decoding_controller.decoder_update()

    @pyqtSlot()
    def update_decodings(self):
        self.compare_frame_controller.load_decodings()
        self.compare_frame_controller.fill_decoding_combobox()
        self.compare_frame_controller.refresh_existing_encodings()

        self.generator_tab_controller.refresh_existing_encodings(self.compare_frame_controller.decodings)

    @pyqtSlot(int)
    def on_selected_tab_changed(self, index: int):
        if index == 0:
            self.undo_group.setActiveStack(self.signal_tab_controller.signal_undo_stack)
        elif index == 1:
            self.undo_group.setActiveStack(self.compare_frame_controller.protocol_undo_stack)
            self.compare_frame_controller.ui.tblViewProtocol.resize_columns()
            self.compare_frame_controller.ui.tblViewProtocol.resize_vertical_header()
            h = max(self.compare_frame_controller.ui.btnSaveProto.height(),
                    self.generator_tab_controller.ui.btnSave.height())
            self.compare_frame_controller.ui.btnSaveProto.setMinimumHeight(h)

            th = self.compare_frame_controller.ui.tabWidget.tabBar().height()
            for i in range(self.compare_frame_controller.ui.tabWidget.count()):
                self.compare_frame_controller.ui.tabWidget.widget(i).layout().setContentsMargins(0, 7 + h - th, 0, 0)

        elif index == 2:
            self.undo_group.setActiveStack(self.generator_tab_controller.generator_undo_stack)
            h = max(self.compare_frame_controller.ui.btnSaveProto.height(),
                    self.generator_tab_controller.ui.btnSave.height())
            self.generator_tab_controller.ui.btnSave.setMinimumHeight(h)
            th = self.generator_tab_controller.ui.tabWidget.tabBar().height()
            for i in range(self.generator_tab_controller.ui.tabWidget.count()):
                self.generator_tab_controller.ui.tabWidget.widget(i).layout().setContentsMargins(0, 7 + h - th, 0, 0)

    @pyqtSlot()
    def on_show_record_dialog_action_triggered(self):
        pm = self.project_manager
        try:
            r = ReceiveDialogController(pm, parent=self)
        except OSError as e:
            logger.error(repr(e))
            return

        if r.has_empty_device_list:
            Errors.no_device()
            r.close()
            return

        r.recording_parameters.connect(pm.set_recording_parameters)
        r.files_recorded.connect(self.on_signals_recorded)
        r.show()

    @pyqtSlot()
    def show_proto_sniff_dialog(self):
        pm = self.project_manager
        signal = next((proto.signal for proto in self.compare_frame_controller.protocol_list), None)

        bit_len = signal.bit_len          if signal else 100
        mod_type = signal.modulation_type if signal else 1
        tolerance = signal.tolerance      if signal else 5
        noise = signal.noise_threshold    if signal else 0.001
        center = signal.qad_center        if signal else 0.02

        psd = ProtocolSniffDialogController(pm, noise, center, bit_len, tolerance, mod_type,
                                            self.compare_frame_controller.decodings,
                                            encoding_index=self.compare_frame_controller.ui.cbDecoding.currentIndex(),
                                            parent=self)

        if psd.has_empty_device_list:
            Errors.no_device()
            psd.close()
        else:
            psd.recording_parameters.connect(pm.set_recording_parameters)
            psd.protocol_accepted.connect(self.compare_frame_controller.add_sniffed_protocol_messages)
            psd.show()

    @pyqtSlot()
    def on_show_spectrum_dialog_action_triggered(self):
        pm = self.project_manager
        r = SpectrumDialogController(pm, parent=self)
        if r.has_empty_device_list:
            Errors.no_device()
            r.close()
            return

        r.recording_parameters.connect(pm.set_recording_parameters)
        r.show()

    @pyqtSlot(list)
    def on_signals_recorded(self, file_names: list):
        QApplication.instance().setOverrideCursor(Qt.WaitCursor)
        for filename in file_names:
            self.add_signalfile(filename)
        QApplication.instance().restoreOverrideCursor()

    @pyqtSlot()
    def show_options_dialog_action_triggered(self):
        self.show_options_dialog_specific_tab(tab_index=0)

    @pyqtSlot()
    def on_new_project_action_triggered(self):
        pdc = ProjectDialogController(parent=self)
        pdc.finished.connect(self.on_project_dialog_finished)
        pdc.show()

    @pyqtSlot()
    def on_project_settings_action_triggered(self):
        self.show_project_settings()

    @pyqtSlot()
    def on_edit_menu_about_to_show(self):
        self.ui.actionShowFileTree.setChecked(self.ui.splitter.sizes()[0] > 0)

    @pyqtSlot()
    def on_action_show_filetree_triggered(self):
        if self.ui.splitter.sizes()[0] > 0:
            self.ui.splitter.setSizes([0, 1])
        else:
            self.ui.splitter.setSizes([1, 1])

    @pyqtSlot()
    def on_project_dialog_finished(self):
        if self.sender().committed:
            if self.sender().new_project:
                for f in self.signal_tab_controller.signal_frames:
                    self.close_signal_frame(f)

            self.project_manager.from_dialog(self.sender())

    @pyqtSlot()
    def on_open_file_action_triggered(self):
        self.show_open_dialog(directory=False)

    @pyqtSlot()
    def on_open_directory_action_triggered(self):
        self.show_open_dialog(directory=True)

    def show_open_dialog(self, directory=False):
        fip = FileIconProvider()
        self.dialog = QFileDialog(self)
        self.dialog.setIconProvider(fip)
        self.dialog.setDirectory(FileOperator.RECENT_PATH)
        self.dialog.setWindowTitle("Open Folder")
        if directory:
            self.dialog.setFileMode(QFileDialog.Directory)
        else:
            self.dialog.setFileMode(QFileDialog.ExistingFiles)
            self.dialog.setNameFilter(
                "All files (*);;Complex (*.complex);;Complex16 unsigned (*.complex16u);;Complex16 signed (*.complex16s);;Wave (*.wav);;Protocols (*.proto);;"
                "Fuzzprofiles (*.fuzz);;Tar Archives (*.tar *.tar.gz *.tar.bz2);;Zip Archives (*.zip)")

        self.dialog.setOptions(QFileDialog.DontResolveSymlinks)
        self.dialog.setViewMode(QFileDialog.Detail)

        if self.dialog.exec_():
            try:
                file_names = self.dialog.selectedFiles()
                folders = [folder for folder in file_names if os.path.isdir(folder)]

                if len(folders) > 0:
                    folder = folders[0]
                    for f in self.signal_tab_controller.signal_frames:
                        self.close_signal_frame(f)

                    self.project_manager.set_project_folder(folder)
                else:
                    self.setCursor(Qt.WaitCursor)
                    file_names = FileOperator.uncompress_archives(file_names, QDir.tempPath())
                    self.add_files(file_names)
                    self.unsetCursor()
            except Exception as e:
                Errors.generic_error(self.tr("Failed to open"), str(e), traceback.format_exc())
                QApplication.instance().restoreOverrideCursor()

    @pyqtSlot()
    def on_close_all_action_triggered(self):
        self.close_all()

    @pyqtSlot(list)
    def on_files_dropped(self, files):
        """
        :type files: list of QtCore.QUrl
        """
        self.__add_urls_to_group(files, group_id=0)

    @pyqtSlot(list, int)
    def on_files_dropped_on_group(self, files, group_id: int):
        """
        :param group_id:
        :type files: list of QtCore.QUrl
        """
        self.__add_urls_to_group(files, group_id=group_id)

    def __add_urls_to_group(self, file_urls, group_id=0):
        local_files = [file_url.toLocalFile() for file_url in file_urls if file_url.isLocalFile()]
        if len(local_files) > 0:
            self.setCursor(Qt.WaitCursor)
            self.add_files(FileOperator.uncompress_archives(local_files, QDir.tempPath()), group_id=group_id)
            self.unsetCursor()

    @pyqtSlot(list)
    def on_cfc_close_wanted(self, protocols: list):
        frame_protos = {sframe: protocol for sframe, protocol in self.signal_protocol_dict.items() if protocol in protocols}

        for frame in frame_protos:
            self.close_signal_frame(frame)

        for proto in (proto for proto in protocols if proto not in frame_protos.values()):
            # close protocols without associated signal frame
            self.close_protocol(proto)

    @pyqtSlot(dict)
    def on_options_changed(self, changed_options: dict):
        refresh_protocol_needed = "show_pause_as_time" in changed_options

        if refresh_protocol_needed:
            for sf in self.signal_tab_controller.signal_frames:
                sf.refresh_protocol()

        self.compare_frame_controller.refresh_field_types_for_labels()
        self.compare_frame_controller.set_shown_protocols()
        self.generator_tab_controller.set_network_sdr_send_button_visibility()
        self.generator_tab_controller.init_rfcat_plugin()

        if "default_view" in changed_options:
            self.apply_default_view(int(changed_options["default_view"]))

    @pyqtSlot()
    def on_text_edit_project_description_text_changed(self):
        self.project_manager.description = self.ui.textEditProjectDescription.toPlainText()

    @pyqtSlot()
    def on_btn_file_tree_go_up_clicked(self):
        cur_dir = self.filemodel.rootDirectory()
        if cur_dir.cdUp():
            path = cur_dir.path()
            self.filemodel.setRootPath(path)
            self.ui.fileTree.setRootIndex(self.file_proxy_model.mapFromSource(self.filemodel.index(path)))