Exemple #1
0
    def handleSuggestPlaylist(self, result):
        if 'lists' in result:
            if self._lists != result['lists']:
                self._lists = result['lists']
                self._suggestPlayListModel.clear()
            else:
                return

            lists = self._lists
            for playlist in lists:
                index = lists.index(playlist)
                _list = {}
                _list['listId'] = playlist['listId']
                _list['listName'] = playlist['listName']
                _list['playAll'] = playlist['playAll']

                if self.isPlaylistCoverExisted(playlist['listName']):
                    _list['cover'] = self.getPlaylistCoverPath(playlist[
                        'listName'])
                else:
                    d = PlaylistCover360Runnable(
                        index, self, playlist['listName'], playlist['image'])
                    QThreadPool.globalInstance().start(d)

                obj = QmlSuggestPlaylistObject(**_list)
                self._suggestPlayListModel.append(obj)
Exemple #2
0
 def __init__(self):
     super(CoverWorker, self).__init__()
     QThreadPool.globalInstance().setMaxThreadCount(4)
     self.downloadArtistCoverSuccessed.connect(self.cacheArtistCover)
     self.downloadAlbumCoverSuccessed.connect(self.cacheAlbumCover)
     self.artistCovers = {}
     self.albumCovers = {}
Exemple #3
0
 def downloadOnlineAlbumCover(self, artist, title, url, medias):
     f = self.onlineSongCoverPath(artist, title)
     if os.path.exists(f):
         return
     if url:
         d = AlbumCover360Runnable(self, artist, title, url, medias)
         QThreadPool.globalInstance().start(d)
Exemple #4
0
    def handleOnlineSongs(self, result):
        self._searchOnlineSongObjsListModel.clear()
        self._searchOnlineAlbumObjsListModel.clear()
        if 'songList' in result:
            songList = result['songList']

            for song in songList:
                song['url'] = ""
                song['title'] = song['songName']
                song['artist'] = song['singerName']
                song['album'] = song['albumName']
                song['songId'] = int(song['songId'])
                song['singerId'] = int(song['singerId'])
                song['albumId'] = int(song['albumId'])
                obj = QmlOnlineSongObject(**song)
                self._searchOnlineSongObjsListModel.append(obj)

        if 'albumList' in result and 'data' in result['albumList']:
            albumList = result['albumList']['data']
            for album in albumList:
                index = albumList.index(album)
                album['artist'] = album['singerName']
                album['album'] = album['albumName']
                if self.isAlbumCoverExisted(album['artist'], album['album']):
                    album['cover'] = self.getAlbumCoverPath(album['artist'],
                                                            album['album'])
                else:
                    d = AlbumCover360Runnable(index, self, album['artist'],
                                              album['album'],
                                              album['albumImage'])
                    QThreadPool.globalInstance().start(d)

                obj = QmlOnlineAlbumObject(**album)
                self._searchOnlineAlbumObjsListModel.append(obj)
    def load_children(self, item: QStandardItemModel = None) -> None:
        if not self.client:
            self.set_loading_cursor(False)
            return

        self.set_loading_cursor(True)
        loader = ContentLoader(self, item)
        QThreadPool.globalInstance().start(loader)
Exemple #6
0
    def run_worker(self, task, callback):
        """Runs a task in another thread.

        The `task` must be an object that implements a `run()`
        method. Completion is notified to the given `callback` function.

        """
        worker = Worker(task)
        worker.finished.connect(callback)
        QThreadPool.globalInstance().start(worker)
Exemple #7
0
 def __init__(self, parent=None):
     super(CoverWorker, self).__init__(parent)
     QThreadPool.globalInstance().setMaxThreadCount(50)
     self.albumCoverThreadPool.setMaxThreadCount(50)
     self.artistCovers = {}
     self.albumCovers = {}
     self.onlineSongCovers = {}
     self.taskNumber = 0
     self._artists = set()
     self._albums = set()
     self.initConnect()
    def addSong(self, media):
        _songDict = self.updateTags(media)
        url = media['url']
        self._songsDict[url] = _songDict
        songObj = QmlOnlineSongObject(**_songDict)
        self._songObjs[url] = songObj

        if not songObj.playlinkUrl:
            d = RequestSongRunnable(self, url)
            QThreadPool.globalInstance().start(d)
        else:
            self.downloadCover(_songDict)
Exemple #9
0
    def __init__(self,
      # A number *n* to create a pool of *n* simple threads, where each thread
      # lacks an event loop, so that it can emit but not receive signals.
      # This means that g_ may **not** be run in a thread of this pool,
      # without manually adding a event loop. If *n* < 1, the global thread
      # pool is used.
      maxThreadCount,

      # See parent_.
      parent=None):

        super().__init__(parent)
        if maxThreadCount < 1:
            self.threadPool = QThreadPool.globalInstance()
        else:
            self.threadPool = QThreadPool(self)
            self.threadPool.setMaxThreadCount(maxThreadCount)
Exemple #10
0
 def downloadArtistCover(self, artist):
     f = self.artistCoverPath(artist)
     if os.path.exists(f):
         return
     if ',' in artist:
         artist = artist.split(',')
         for item in artist:
             if item not in self._artists:
                 self._artists.add(item)
                 self.taskNumber += 1
                 d = CoverRunnable(self, item, qtype="artist")
                 QThreadPool.globalInstance().start(d)
     else:
         if artist not in self._artists:
             self._artists.add(artist)
             self.taskNumber += 1
             d = CoverRunnable(self, artist, qtype="artist")
             QThreadPool.globalInstance().start(d)
Exemple #11
0
class AsyncPoolController(_AsyncAbstractController):
    def __init__(self,
      # A number *n* to create a pool of *n* simple threads, where each thread
      # lacks an event loop, so that it can emit but not receive signals.
      # This means that g_ may **not** be run in a thread of this pool,
      # without manually adding a event loop. If *n* < 1, the global thread
      # pool is used.
      maxThreadCount,

      # See parent_.
      parent=None):

        super().__init__(parent)
        if maxThreadCount < 1:
            self.threadPool = QThreadPool.globalInstance()
        else:
            self.threadPool = QThreadPool(self)
            self.threadPool.setMaxThreadCount(maxThreadCount)

    # See `_start`_.
    def _start(self, future):
        # Asynchronously invoke f_.
        apw = _AsyncPoolWorker(future)
        self.threadPool.start(apw)

    # See `_terminate`_.
    def _terminate(self):
        self.threadPool.waitForDone()
        del self.threadPool
Exemple #12
0
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self._counter = 0
        self.init_ui()

        self._threadpool = QThreadPool()
        #self._threadpool = QtCore.QThreadPool.globalInstance()
        #self._threadpool.setMaxThreadCount(2)
        print("Multithreading with maximum {} threads" .format(self._threadpool.maxThreadCount()))

        self._timer = QTimer()
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self.recurring_timer)
        self._timer.start()
Exemple #13
0
 def close(self):
     QThreadPool.globalInstance().clear()
     mediaPlayer.stop()
     configWorker.save()
     playlistWorker.savePlaylists()
Exemple #14
0
    def run(self):
        engine = NetEaseEngine()
        if self.qtype == "artist":
            url = engine.searchCoverByArtistName(self.name)
        elif self.qtype == "album":
            url = engine.searchCoverByAlbumName(self.name)

        coverWorker.receiveCover.emit(self.qtype, self.name, url)


if __name__ == "__main__":
    app = QGuiApplication(sys.argv)

    artists = []
    for artist in db.get_cursor().execute("Select name from artist").fetchall():
        artists.append(artist)

    albums = []
    for album in db.get_cursor().execute("Select name from album").fetchall():
        albums.append(album)

    for artist in artists:
        d = DRunnable(artist, qtype="artist")
        QThreadPool.globalInstance().start(d)
    for album in albums:
        d = DRunnable(album, qtype="album")
        QThreadPool.globalInstance().start(d)

    exitCode = app.exec_()
    sys.exit(exitCode)
Exemple #15
0
 def restoreSongs(self, songs):
     d = RestoreDBRunnable(self, songs)
     QThreadPool.globalInstance().start(d)
Exemple #16
0
 def close(self):
     QThreadPool.globalInstance().clear()
     mediaPlayer.stop()
     configWorker.save()
     playlistWorker.savePlaylists()
Exemple #17
0
    def __init__(self, appctxt, BbRouter, download_dir,
                 modules: List[Tuple[str,
                                     str]], last_dialog: QtWidgets.QDialog):
        """Download Dialog for selecting files to download/ignore

        Args:
            appctxt (ApplicationContext): fbs application context
            BbRouter (str): authentication token
            download_dir (str): download directory
            modules (List[Tuple[str, str]]): list of course name and course id tuples
            last_dialog (QtWidgets.QDialog): last dialog to return on back button press
        """
        super(DownloadDialog, self).__init__()
        uic.loadUi(appctxt.get_resource("layouts/download.ui"), self)

        self.logger = Logger(appctxt)

        self.appctxt = appctxt
        self.BbRouter = BbRouter
        self.download_dir = download_dir
        self.modules = modules
        self.last_dialog = last_dialog
        dirLabel = self.findChild(QtWidgets.QLabel, "downloadDirLabel")
        dirLabel.setText("Downloading to: {}".format(download_dir))

        # load icons
        backIcon = QtGui.QIcon(appctxt.get_resource("images/back.png"))
        self.folderIcon = QtGui.QIcon(
            appctxt.get_resource("images/folder.png"))
        self.videoIcon = QtGui.QIcon(appctxt.get_resource("images/video.png"))
        self.fileIcon = QtGui.QIcon(appctxt.get_resource("images/file.png"))

        # load buttons
        self.backButton = self.findChild(QtWidgets.QToolButton, "backButton")
        self.backButton.setIcon(backIcon)
        self.ignoreButton = self.findChild(QtWidgets.QPushButton,
                                           "ignoreButton")
        self.downloadButton = self.findChild(QtWidgets.QPushButton,
                                             "downloadButton")
        self.selectAllButton = self.findChild(QtWidgets.QPushButton,
                                              "selectAllButton")
        self.deselectAllButton = self.findChild(QtWidgets.QPushButton,
                                                "deselectAllButton")
        self.reloadButton = self.findChild(QtWidgets.QPushButton,
                                           "reloadButton")
        self.selectFilesButton = self.findChild(QtWidgets.QPushButton,
                                                "selectFilesButton")
        self.selectVideosButton = self.findChild(QtWidgets.QPushButton,
                                                 "selectVideosButton")

        self.backButton.clicked.connect(self.handle_back)
        self.selectAllButton.clicked.connect(self.handle_select_all)
        self.deselectAllButton.clicked.connect(self.handle_unselect_all)
        self.ignoreButton.clicked.connect(self.handle_ignore)
        self.downloadButton.clicked.connect(self.handle_download)
        self.reloadButton.clicked.connect(self.handle_reload)
        self.selectFilesButton.clicked.connect(self.handle_select_files)
        self.selectVideosButton.clicked.connect(self.handle_select_videos)

        self.progressBar = self.findChild(QtWidgets.QProgressBar,
                                          "progressBar")
        self.progressBar.setValue(0)

        self.downloadProgressText = self.findChild(QtWidgets.QLabel,
                                                   "downloadProgressText")
        self.downloadProgressText.setText(
            "Click download to start downloading files")

        # get download dir from NTU Learn and load tree
        self.threadPool = QThreadPool()
        self.tree = self.findChild(QtWidgets.QTreeWidget, "treeWidget")

        # NOTE do not show tree even though we have data as we want the user to
        # act on fresh download data
        self.storage = Storage(download_dir)
        self.data = self.storage.download_dir

        # add loading text
        node = QtWidgets.QTreeWidgetItem(self.tree)
        node.setText(0, "Click Reload to pull data from NTU Learn")

        self.show()
Exemple #18
0
    def createImageData(main_window,
                        image_files,
                        output_image,
                        *finish_fn_args,
                        info_var=None,
                        convert_numpy=False,
                        convert_raw=True,
                        resample=False,
                        target_size=0.125,
                        crop_image=False,
                        origin=(0, 0, 0),
                        target_z_extent=(0, 0),
                        tempfolder=None,
                        finish_fn=None,
                        **finish_fn_kwargs):
        # print("Create image data")
        if len(image_files) == 1:
            image = image_files[0]
            file_extension = os.path.splitext(image)[1]

        else:
            for image in image_files:
                file_extension = imghdr.what(image)
                if file_extension != 'tiff':
                    main_window.e(
                        '', '',
                        'When reading multiple files, all files must TIFF formatted.'
                    )
                    error_title = "Read Error"
                    error_text = "Error reading file: ({filename})".format(
                        filename=image)
                    displayFileErrorDialog(main_window,
                                           message=error_text,
                                           title=error_title)
                    return

        if file_extension in ['.mha', '.mhd']:
            createProgressWindow(main_window, "Converting", "Converting Image")
            image_worker = Worker(loadMetaImage, main_window, image,
                                  output_image, info_var, resample,
                                  target_size, crop_image, origin,
                                  target_z_extent, convert_numpy, convert_raw,
                                  tempfolder)

        elif file_extension in ['.npy']:
            createProgressWindow(main_window, "Converting", "Converting Image")
            image_worker = Worker(loadNpyImage, image, output_image, info_var,
                                  resample, target_size, crop_image, origin,
                                  target_z_extent)

        elif file_extension in ['tif', 'tiff', '.tif', '.tiff']:
            reader = vtk.vtkTIFFReader()
            reader.AddObserver("ErrorEvent", main_window.e)
            createProgressWindow(main_window, "Converting", "Converting Image")
            image_worker = Worker(loadTif, image_files, reader, output_image,
                                  convert_numpy, info_var)

        elif file_extension in ['.raw']:
            if 'file_type' in info_var and info_var['file_type'] == 'raw':
                createConvertRawImageWorker(main_window, image, output_image,
                                            info_var, resample, target_size,
                                            crop_image, origin,
                                            target_z_extent, finish_fn)
                return
            else:  #if we aren't given the image dimensions etc, the user needs to enter them
                main_window.raw_import_dialog = createRawImportDialog(
                    main_window, image, output_image, info_var, resample,
                    target_size, crop_image, origin, target_z_extent,
                    finish_fn)
                dialog = main_window.raw_import_dialog['dialog'].show()
                return

        else:
            main_window.e(
                '', '',
                'File format is not supported. Accepted formats include: .mhd, .mha, .npy, .tif, .raw'
            )
            error_title = "Error"
            error_text = "Error reading file: ({filename})".format(
                filename=image)
            displayFileErrorDialog(main_window,
                                   message=error_text,
                                   title=error_title)
            return

        main_window.progress_window.setValue(10)

        image_worker.signals.progress.connect(
            partial(progress, main_window.progress_window))
        if finish_fn is not None:
            image_worker.signals.finished.connect(
                lambda: finish_fn(*finish_fn_args, **finish_fn_kwargs))
        main_window.threadpool = QThreadPool()
        main_window.threadpool.start(image_worker)
        print("Started worker")
Exemple #19
0
        engine = NetEaseEngine()
        if self.qtype == "artist":
            url = engine.searchCoverByArtistName(self.name)
        elif self.qtype == "album":
            url = engine.searchCoverByAlbumName(self.name)

        coverWorker.receiveCover.emit(self.qtype, self.name, url)


if __name__ == '__main__':
    app = QGuiApplication(sys.argv)

    artists = []
    for artist in db.get_cursor().execute(
            'Select name from artist').fetchall():
        artists.append(artist)

    albums = []
    for album in db.get_cursor().execute('Select name from album').fetchall():
        albums.append(album)

    for artist in artists:
        d = DRunnable(artist, qtype="artist")
        QThreadPool.globalInstance().start(d)
    for album in albums:
        d = DRunnable(album, qtype="album")
        QThreadPool.globalInstance().start(d)

    exitCode = app.exec_()
    sys.exit(exitCode)
Exemple #20
0
    def setupUi(self):

        serialport = QLabel("GPIB port", self)
        self.serialportEdit = QLineEdit(self.k2001aport, self)

        self.runstopButton = QPushButton("START", self)
        self.clearButton = QPushButton("Clear", self)

        schroll_lbl = QLabel("Schroll elapsed time ", self)
        self.combo0 = QComboBox(self)
        mylist0 = ["100", "200", "400", "600", "800", "1000", "1500", "2000"]
        self.combo0.addItems(mylist0)
        self.combo0.setCurrentIndex(mylist0.index(str(self.schroll_pts)))

        ##############################################

        g0_1 = QGridLayout()
        g0_1.addWidget(serialport, 0, 0)
        g0_1.addWidget(self.serialportEdit, 0, 1)
        g0_1.addWidget(schroll_lbl, 0, 2)
        g0_1.addWidget(self.combo0, 0, 3)
        g0_1.addWidget(self.runstopButton, 0, 4)
        g0_1.addWidget(self.clearButton, 0, 5)

        ##############################################

        # set graph  and toolbar to a new vertical group vcan
        self.pw1 = pg.PlotWidget()

        ##############################################

        # create table
        self.tableWidget = self.createTable()

        ##############################################

        # SET ALL VERTICAL COLUMNS TOGETHER
        vbox = QVBoxLayout()
        vbox.addLayout(g0_1)
        vbox.addWidget(self.pw1)

        hbox = QHBoxLayout()
        hbox.addLayout(vbox)
        hbox.addWidget(self.tableWidget)

        self.threadpool = QThreadPool()
        print("Multithreading in the K2001A with maximum %d threads" %
              self.threadpool.maxThreadCount())
        self.isRunning = False

        self.setLayout(hbox)
        self.setWindowTitle("Test Keithley 2001A")

        # PLOT 2 settings
        # create plot and add it to the figure canvas
        self.p1 = self.pw1.plotItem
        self.curve1 = self.p1.plot(pen='w')
        # create plot and add it to the figure
        self.p0_1 = pg.ViewBox()
        self.curve2 = pg.PlotCurveItem(pen='r')
        self.p0_1.addItem(self.curve2)
        # connect respective axes to the plot
        #self.p1.showAxis('left')
        self.p1.getAxis('left').setLabel("Voltage", units="V", color='yellow')
        self.p1.showAxis('right')
        self.p1.getAxis('right').setLabel("Arb unit, 1023=1.1V",
                                          units="",
                                          color='red')
        self.p1.scene().addItem(self.p0_1)
        self.p1.getAxis('right').linkToView(self.p0_1)
        self.p0_1.setXLink(self.p1)

        self.p1.getAxis('bottom').setLabel("Points", units="", color='yellow')
        # Use automatic downsampling and clipping to reduce the drawing load
        self.pw1.setDownsampling(mode='peak')
        self.pw1.setClipToView(True)

        # Initialize and set titles and axis names for both plots
        self.clear_vars_graphs()
        self.combo0.activated[str].connect(self.onActivated0)

        # run or cancel the main script
        self.runstopButton.clicked.connect(self.runstop)
        self.clearButton.clicked.connect(self.set_clear)
        self.clearButton.setEnabled(False)
Exemple #21
0
def using_q_runnable():
    app = QCoreApplication([])
    runnable = Runnable()
    QThreadPool.globalInstance().start(runnable)
    sys.exit(app.exec_())
Exemple #22
0
 def loadSoundsConf(self):
     loadConf=load_conf(config="sounds.json")
     loadConf.signals.hasConf_d.connect(self.storeSoundsInfo)
     loadConf.signals.hasError.connect(logging.error)
     QThreadPool.globalInstance().start(loadConf)
Exemple #23
0
 def saveExercises_(self):
     saveMe=UEC('exercise.json',self.edit_exercise_model.item)
     saveMe.signals.hasErrors.connect(logging.error)
     saveMe.signals.finished.connect(self.reloadConf)
     QThreadPool.globalInstance().start(saveMe)
Exemple #24
0
    def initUI(self):

        #self.hbox = QVBoxLayout(self)
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setContentsMargins(11, 11, 11, 11)

        self.lblCodec = QLabel("Codec", self)
        self.lblAlpha = QLabel("Alpha", self)
        self.lblFrameRate = QLabel("Frame Rate", self)
        self.gridLayout.addWidget(self.lblCodec, 0, 0, 1, 1)
        self.gridLayout.addWidget(self.lblAlpha, 0, 1, 1, 1)
        self.gridLayout.addWidget(self.lblFrameRate, 0, 2, 1, 1)

        self.comboCodec = QComboBox(self)
        self.comboCodec.setMinimumWidth(80)
        self.comboCodec.addItem("UT Video")

        self.comboAlpha = QComboBox(self)
        self.comboAlpha.setMinimumWidth(80)
        self.comboAlpha.addItem("No Alpha")
        self.comboAlpha.addItem("with Alpha")

        self.comboFrameRate = QComboBox(self)
        self.comboFrameRate.setMinimumWidth(80)
        self.comboFrameRate.addItem("24.00")
        self.comboFrameRate.addItem("30.00")

        self.buttonCompress = QPushButton("Compress", self)
        self.buttonCompress.clicked[bool].connect(self.compressPress)

        self.gridLayout.addWidget(self.comboCodec, 1, 0, 1, 1)
        self.gridLayout.addWidget(self.comboAlpha, 1, 1, 1, 1)
        self.gridLayout.addWidget(self.comboFrameRate, 1, 2, 1, 1)
        self.gridLayout.addWidget(self.buttonCompress, 1, 3, 1, 1)

        self.pbList = []

        for i in range(len(self.inList)):
            self.tempPB = QProgressBar(self)
            self.tempPB.setMinimum(0)
            self.tempPB.setMaximum(100)
            self.tempPB.setTextVisible(True)
            self.tempPB.setFormat(str(self.inList[i]) + " %p%")
            self.tempPB.setAlignment(Qt.AlignCenter)
            self.tempPB.setValue(0)
            if i == 0:
                self.defaulStyle = self.tempPB.styleSheet()

            self.gridLayout.addWidget(self.tempPB, i + 2, 0, 1, 4)
            self.pbList.append(self.tempPB)

        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem, len(self.inList) + 2, 0, 1, 1)

        self.comboCodec.activated[str].connect(self.chooseCodec)
        self.comboAlpha.activated[str].connect(self.chooseAlpha)
        self.comboFrameRate.activated[str].connect(self.chooseFrameRate)

        self.setGeometry(300, 300, 390, 100)
        self.gridLayout.setGeometry(QRect(19, 19, 581, 94))
        self.setWindowTitle('FFMpeg Python Compressor')
        self.show()

        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" %
              self.threadpool.maxThreadCount())
Exemple #25
0
# -*- coding: utf-8 -*-

# async guidance from
#  https://martinfitzpatrick.name/article/multithreading-pyqt-applications-with-qthreadpool/
# (didn't use inbuilt python async/await since it requires an event/thread loop which it seems
#  qt itself isn't playing nice with... maybe?)


from PyQt5.QtCore import QRunnable, pyqtSlot, QThreadPool

threadpool = QThreadPool()
print("Multithreading with maximum %d threads" % threadpool.maxThreadCount())

class Worker(QRunnable):
    '''
    Worker thread

    Inherits from QRunnable to handler worker thread setup, signals and wrap-up.

    :param callback: The function callback to run on this worker thread. Supplied args and
                     kwargs will be passed through to the runner.
    :type callback: function
    :param args: Arguments to pass to the callback function
    :param kwargs: Keywords to pass to the callback function

    '''

    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()
        # Store constructor arguments (re-used for processing)
        self.fn = fn
Exemple #26
0
    def __init__(self, *args, obj=None, **Kwargs):
        super(MainWindow, self).__init__(*args, **Kwargs)
        self.setWindowFlags(Qt.WindowCloseButtonHint
                            | Qt.WindowMinimizeButtonHint)
        self.setupUi(self)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.MinimumExpanding)
        self.setSizePolicy(sizePolicy)
        self.setGeometry(0, 0, gv.WIDTH, gv.HEIGHT)
        self.setMaximumSize(QSize(gv.WIDTH, gv.HEIGHT))

        # Connect to database
        self.db = cuf.db_connect("QSQLITE", "pa_db.db")
        self.db.open()

        ###################################################################################
        #region MainWindow SETUP

        # Toggle function
        self.menu_toggle_btn.clicked.connect(
            lambda status, self=self: uif.toggle_menu(self, status))

        #Page change settings
        self.home_btn.clicked.connect(lambda status, self=self, idx=0: uif.
                                      change_page(self, idx, status))
        self.anchor_btn.clicked.connect(lambda status, self=self, idx=1: uif.
                                        change_page(self, idx, status))
        self.sub_btn.clicked.connect(lambda status, self=self, idx=2: uif.
                                     change_page(self, idx, status))
        self.settings_btn.clicked.connect(lambda status, self=self, idx=3: uif.
                                          change_page(self, idx, status))
        self.add_btn.clicked.connect(lambda status, self=self, idx=4: uif.
                                     change_page(self, idx, status))

        #endregion MainWindow SETUP
        ###################################################################################

        # set Current
        #######################################################################
        #region PAGE ONE CONFIG
        # define Slot for update image.
        Page1 = self.page1
        currentFrame = None  # store value of current frame for

        @pyqtSlot()
        def processedImage(lpText, img):
            qt_img = convert_cv_to_qt(img)
            self.page1.feed.setPixmap(qt_img)

        def convert_cv_to_qt(img):
            h, w, ch = img.shape
            bytes_per_line = ch * w
            convert_cv_to_Qt_format = QImage(img.data, w, h,
                                             QImage.Format_RGB888)
            currentFrame = img
            p = convert_cv_to_Qt_format.scaled(gv.FeedWidth, gv.FeedHeight,
                                               Qt.KeepAspectRatio)
            return QPixmap.fromImage(p)

        # function to emit requestFrame signl
        def scanFrame():
            # change global status of image process
            gv.ProcessFrame = True

        self.feedthread = QThreadPool()
        self.feedWorker = FeedWorker()
        self.feedWorker.signals.processedImage.connect(processedImage)
        self.feedthread.start(self.feedWorker)

        Page1.cam_scan_btn.clicked.connect(scanFrame)
        #endregion PAGE ON CONFIG
        ########################################################################

        ######################################################################
        #region Page Two Config
        page2 = self.page2

        query = QSqlQuery("SELECT * FROM Client")
        page2.db_table.show_data(query)
        #endregion Page Two Config
        ######################################################################

        ######################################################################
        #region Page Three Config
        page3 = self.page3
        query = QSqlQuery("SELECT * FROM Client")
        page3.db_table.show_data(query)
        #endregion Page Three Config
        ######################################################################

        # clos database connection
        self.db.close()
Exemple #27
0
class MainWindow(QMainWindow):
    """
    You can use @pyqtSlot(int) syntax (with parameters), or you can pass this,
    but it make code more readable.
    Вы можете использовать синтаксис объявления слотов @pyqtSlot(int)
    с указанием типа передаваемых значений, или опустить его вовсе,
    однако это делает код нагляднее
    и позволяет быстро понять, что слот, а что - функция.
    """

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self._counter = 0
        self.init_ui()

        self._threadpool = QThreadPool()
        #self._threadpool = QtCore.QThreadPool.globalInstance()
        #self._threadpool.setMaxThreadCount(2)
        print("Multithreading with maximum {} threads" .format(self._threadpool.maxThreadCount()))

        self._timer = QTimer()
        self._timer.setInterval(1000)
        self._timer.timeout.connect(self.recurring_timer)
        self._timer.start()

    def init_ui(self):
        layout = QVBoxLayout()

        self._label = QLabel("Start")
        b = QPushButton("Start QRunnable")
        b.pressed.connect(self.start_new_runnable)

        layout.addWidget(self._label)
        layout.addWidget(b)

        w = QWidget()
        w.setLayout(layout)

        self.setCentralWidget(w)

    @pyqtSlot(int)
    def thread_progress_fn(self, n):
        print("{}% done".format(n))

    @pyqtSlot(object)
    def thread_print_output(self, s):
        print('Result: {}'.format(s))

    @pyqtSlot()
    def thread_complete(self):
        print("QRunnable worker COMPLETE!")

    @pyqtSlot(tuple)
    def thread_error(self, err):
        QMessageBox.warning(self, "Warning!", err[1], QMessageBox.Ok)
        print('Error {}\n{}'.format(err[1], err[2]))

    @pyqtSlot()
    def start_new_runnable(self):
        # Pass the function to execute
        worker = Worker(1, debug=True) # Any other args, kwargs are passed to the run function
        worker.signals.result.connect(self.thread_print_output)
        worker.signals.finished.connect(self.thread_complete)
        worker.signals.progress.connect(self.thread_progress_fn)
        worker.signals.error.connect(self.thread_error)
        worker.setAutoDelete(True)
        # Execute (tryStart() better than start() )
        if self._threadpool.tryStart(worker) is False:
            print("Can't create worker!")
            QMessageBox.warning(self, "Warning!", "Can't create worker!", QMessageBox.Ok)

    @pyqtSlot()
    def recurring_timer(self):
        self._counter += 1
        self._label.setText("Counter: {}".format(self._counter))
        print('Active thread count: {}'.format(self._threadpool.activeThreadCount()))

    def closeEvent(self, event):
        """Main window closed, override PyQt5 widget function"""
        print('Try to exit, active thread count: {}'.format(self._threadpool.activeThreadCount()))
        reply = QMessageBox.question(self, 'Message',
                                     "Are you sure to quit?", QMessageBox.Yes |
                                     QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self._threadpool.waitForDone()
            self._timer.stop()
            event.accept()
        else:
            event.ignore()
Exemple #28
0
class ActionWidget(QWidget):
    def __init__(self, parent=None, dev=None):
        super(ActionWidget, self).__init__(parent)
        self.setStyleSheet("background-color: black;")
        vbox = QVBoxLayout()
        self.dev = dev
        self.action = ActionLabel(self)
        self.timerlabel = TimerLabel(self)
        vbox.addWidget(self.action)
        vbox.addWidget(self.timerlabel)
        vbox.setContentsMargins(QMargins(0, 0, 0, 0))
        self.setLayout(vbox)
        # Workers
        self.threadpool = QThreadPool()
        self.quit_thread = False
        self._active_listen = True
        # Timer
        self._interval_done = True
        self._interval_time = 0
        self._timer = QTimer()
        self._timer.timeout.connect(self.iterate)
        # Sound
        self.timer_sound = QSound(TIMER_FX)
        self.interval_sound = QSound(TIMER_FX3)
        # Button
        self._button = None
        # ON EXIT
        self.thread_done = False

        self.start_action_signal()

    def toggle_led(self):
        self._active_listen = False
        self.dev.wr_cmd("pyb.LED(1).toggle()")
        self.action.toggle()
        self._active_listen = True
        if self.action.value:
            self._timer.start(1000)
        else:
            self._timer.stop()

    def update_state(self, state):
        self.action.toggle()
        self._button.pushbutton(True)
        if state == "ON":
            self._timer.start(1000)
        else:
            self._timer.stop()

    def listen_action_state(self, progress_callback):
        while not self.quit_thread:
            if self._active_listen:
                if self.dev.serial.readable() and self.dev.serial.in_waiting:
                    state = self.dev.serial.readline().decode().replace(
                        '\r\n', '')
                    progress_callback.emit(state)
                    print(state)
            time.sleep(0.1)

        print('Thread Done!')
        self.thread_done = True

    def start_action_signal(self):
        # Pass the function to execute
        # Any other args, kwargs are passed to the run function
        worker_led = Worker(self.listen_action_state)
        # worker.signals.result.connect(self.print_output)
        # worker.signals.finished.connect(self.thread_complete)
        # worker.signals.progress.connect(self.progress_fn)
        worker_led.signals.progress.connect(self.update_state)

        # Execute
        self.threadpool.start(worker_led)

    def iterate(self):
        try:
            if self._interval_done:
                interval_type, self._interval_time = next(
                    self.timerlabel._int_gen)
                self.action.setStyleSheet(
                    self.action._type_action_style[interval_type])
                self.action.setText(self.action._type_action[interval_type])
                self.timerlabel.setText(
                    str(timedelta(
                        seconds=self._interval_time)).split('.')[0][2:])
                self._interval_done = False
            else:
                self._interval_time -= 1
                if self._interval_time > 0 and self._interval_time <= 3:
                    self.timer_sound.play()
                elif self._interval_time == 0:
                    self._interval_done = True
                    self.interval_sound.play()
                self.timerlabel.setText(
                    str(timedelta(
                        seconds=self._interval_time)).split('.')[0][2:])

        except StopIteration:
            self.toggle_led()
            self.finish_state()
            self.timerlabel.reset_intervals()
            self._button.pushbutton(True)

    def finish_state(self):
        self.action.setStyleSheet(self.action.finished_bg)
        self.action.setText("Finished")
        self.timerlabel.setText("00:00")

    def closeEvent(self, event):
        self._timer.stop()
        self.quit_thread = True
        try:
            while not self.thread_done:
                time.sleep(0.5)
                print("shutdown...")
        except Exception as e:
            print(e)
        print("SHUTDOWN COMPLETE")
        sys.exit()
Exemple #29
0
    def cacheAlbumCover(self, artist, album, url):
        # print artist, album, url
        self.albumCovers[album] = url

    def downloadArtistCover(self, artist):
        d = CoverRunnable(self, artist, qtype="artist")
        QThreadPool.globalInstance().start(d)

    def downloadAlbumCover(self, artist, album):
        d = CoverRunnable(self, artist, album, qtype="artist")
        QThreadPool.globalInstance().start(d)


if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    QThreadPool.globalInstance().setMaxThreadCount(10)
    from peewee import *
    MusicDBFile = '/home/djf/.config/DeepinMusic3/music.db'
    db = SqliteDatabase(MusicDBFile, threadlocals=True)
    db.connect()

    coverWorker = CoverWorker()
    artists = []
    for artist in db.get_cursor().execute('Select name from artist').fetchall():
        artists.append(artist[0])
    for artist in artists:
        coverWorker.downloadArtistCover(artist)

    albums = []
    for artist, album in db.get_cursor().execute(
            'Select artist, name from album').fetchall():
Exemple #30
0
class MainWindow(QWidget):
    def __init__(self, inList):
        super().__init__()
        self.inList = inList
        self.codec = 'utvideo'
        self.alpha = False
        self.frameRate = 24
        self.defaulStyle = ''
        self.initUI()

    def initUI(self):

        #self.hbox = QVBoxLayout(self)
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setContentsMargins(11, 11, 11, 11)

        self.lblCodec = QLabel("Codec", self)
        self.lblAlpha = QLabel("Alpha", self)
        self.lblFrameRate = QLabel("Frame Rate", self)
        self.gridLayout.addWidget(self.lblCodec, 0, 0, 1, 1)
        self.gridLayout.addWidget(self.lblAlpha, 0, 1, 1, 1)
        self.gridLayout.addWidget(self.lblFrameRate, 0, 2, 1, 1)

        self.comboCodec = QComboBox(self)
        self.comboCodec.setMinimumWidth(80)
        self.comboCodec.addItem("UT Video")

        self.comboAlpha = QComboBox(self)
        self.comboAlpha.setMinimumWidth(80)
        self.comboAlpha.addItem("No Alpha")
        self.comboAlpha.addItem("with Alpha")

        self.comboFrameRate = QComboBox(self)
        self.comboFrameRate.setMinimumWidth(80)
        self.comboFrameRate.addItem("24.00")
        self.comboFrameRate.addItem("30.00")

        self.buttonCompress = QPushButton("Compress", self)
        self.buttonCompress.clicked[bool].connect(self.compressPress)

        self.gridLayout.addWidget(self.comboCodec, 1, 0, 1, 1)
        self.gridLayout.addWidget(self.comboAlpha, 1, 1, 1, 1)
        self.gridLayout.addWidget(self.comboFrameRate, 1, 2, 1, 1)
        self.gridLayout.addWidget(self.buttonCompress, 1, 3, 1, 1)

        self.pbList = []

        for i in range(len(self.inList)):
            self.tempPB = QProgressBar(self)
            self.tempPB.setMinimum(0)
            self.tempPB.setMaximum(100)
            self.tempPB.setTextVisible(True)
            self.tempPB.setFormat(str(self.inList[i]) + " %p%")
            self.tempPB.setAlignment(Qt.AlignCenter)
            self.tempPB.setValue(0)
            if i == 0:
                self.defaulStyle = self.tempPB.styleSheet()

            self.gridLayout.addWidget(self.tempPB, i + 2, 0, 1, 4)
            self.pbList.append(self.tempPB)

        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem, len(self.inList) + 2, 0, 1, 1)

        self.comboCodec.activated[str].connect(self.chooseCodec)
        self.comboAlpha.activated[str].connect(self.chooseAlpha)
        self.comboFrameRate.activated[str].connect(self.chooseFrameRate)

        self.setGeometry(300, 300, 390, 100)
        self.gridLayout.setGeometry(QRect(19, 19, 581, 94))
        self.setWindowTitle('FFMpeg Python Compressor')
        self.show()

        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" %
              self.threadpool.maxThreadCount())

    '''
	Button functions
	'''

    def chooseAlpha(self, text):
        switcher = {"No Alpha": False, "with Alpha": True}
        self.alpha = switcher.get(text, "Invalid day of week")
        #print (self.alpha)

    def chooseCodec(self, text):
        switcher = {"UT Video": "utvideo"}
        self.codec = switcher.get(text, "Invalid day of week")
        #print (self.codec)

    def chooseFrameRate(self, text):
        self.frameRate = float(text)
        #print (self.frameRate)

    def currentData(self, widget):
        return widget.currentText()

    def pushTest(self):
        print("pressed")
        for pb in self.pbList:
            count = 0
            while count < TIME_LIMIT:
                count += 2
                time.sleep(0.5)
                pb.setValue(count)

    #time as HH:MM:SS.mm as timeobject, framerate as float
    def timeToFrames(self, t, frameRate):
        return floor(t.hour * 60 * 60 * 60 * frameRate +
                     t.minute * 60 * 60 * frameRate + t.second * frameRate +
                     t.microsecond / 1000000 * frameRate)

    #time as string as "HH:MM:SS.mm"
    def stringToTime(self, timeString):
        return (datetime.strptime(timeString, "%H:%M:%S.%f"))

    def progress_fn(self, n):
        #print("%d%% done" % n)
        return n

    def getProcessPercent(self, process, frameRate, pySignalObj):
        for line in process.stdout:
            frameLine = re.search("^frame=.*fps=", line)
            durationLine = re.search("^  Duration: ", line)
            if (durationLine):
                dTimeString = re.findall("\d{1,2}:\d{2}:\d{2}.\d{2}", line)
                if (dTimeString):
                    duration = self.stringToTime(dTimeString[0])
                    durationFrames = self.timeToFrames(duration, frameRate)
            if (frameLine):
                frameString = re.findall("[0-9]+", line)
                if (frameString):
                    #test for errors here
                    try:
                        #self.worker.signals.progress.emit(int(frameString[0])/durationFrames * 100)

                        pySignalObj.emit(
                            int(frameString[0]) / durationFrames * 100)
                    except:
                        #self.worker.signals.progress.emit(100)
                        print('setting to -1')
                        raise Exception('error in ffmepg compression')
                        #pySignalObj.emit(-1)
                        #traceback.print_exc()
                        #exctype, value = sys.exc_info()[:2]
                        #self.worker.signals.error.emit( (exctype, value, traceback.format_exc()) )
                        #self.worker.signals.error.emit( ('error') )
                        break

    def execute_this_fn(self, path, codec, alpha, frameRate, progress_callback,
                        errorFFMPEG_callback):
        #print(path)
        pyCompression = pyFFMEGCompress(path, codec, alpha, frameRate)
        ffProcess = pyCompression.ffmpegCompress()

        #with kwargs
        kwargs = {
            'progress_callback': progress_callback,
            'errorFFMPEG_callback': errorFFMPEG_callback
        }
        pyCompression.printProcess(ffProcess, **kwargs)

        #would be nicer to use the class method instead here but doesn't update only prints the final result
        #progress_callback.emit(pyCompression.printProcess(ffProcess))
        '''
		#self.getProcessPercent(ffProcess, frameRate, progress_callback, errorFFMPEG_callback)
		for line in ffProcess.stdout:
			frameLine = re.search("^frame=.*fps=", line)
			durationLine = re.search("^  Duration: ", line)
			if (durationLine):
				dTimeString = re.findall("\d{1,2}:\d{2}:\d{2}.\d{2}", line)
				if (dTimeString):
					duration = self.stringToTime(dTimeString[0])
					durationFrames = self.timeToFrames(duration,frameRate)
			if (frameLine):
				frameString = re.findall("[0-9]+", line)
				if (frameString):
					#test for errors here
					try:
						#self.worker.signals.progress.emit(int(frameString[0])/durationFrames * 100)
						progress_callback.emit(int(frameString[0])/durationFrames * 100)
						#pySignalObj.emit(int(frameString[0])/durationFrames * 100)
					except:
						#self.worker.signals.progress.emit(100)
						#print('setting to -1')
						errorFFMPEG_callback.emit(path + " %p%")
						#raise Exception ('error in ffmepg compression')
						#pySignalObj.emit(-1)
						#traceback.print_exc()
						#exctype, value = sys.exc_info()[:2]
						#self.worker.signals.error.emit( (exctype, value, traceback.format_exc()) )
						#self.worker.signals.error.emit( ('error') )
						break
		'''
        return "Done."

    def print_output(self, s):
        print("Printing output " + str(s))

    def thread_complete(self, r):
        self.i = self.i + 1
        print("THREAD COMPLETE! WITH ERROR " + str(r))

    def errorPB(self, err):
        for o in self.pbList:
            if o.format() == err:
                o.setValue(100)
                o.setStyleSheet(
                    "QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 );border-radius: 3px; border: 1px solid #a60233;}QProgressBar{color:white}"
                )  #("QProgressBar::chunk { background-color: red; }")
                #pb.setStyleSheet("QProgressBar::chunk { background-color: red; }")
                o.setFormat(o.format() + " - Error")

    def resetProgressBar(self, pb, text):
        pb.setValue(0)
        pb.setFormat(text + ' %p%')
        pb.setStyleSheet(self.defaulStyle)

    #figure out how to queue tasks better
    def compressPress(self):
        self.i = 0
        for self.i in range(len(self.pbList)):
            i = self.i
            print(i)
            print(self.i)
            #print(self.pbList[i].format())
            #print(self.pbList[i])
            #print(self.inList[i])

            self.resetProgressBar(self.pbList[i], self.inList[i])

            worker = Worker(
                self.execute_this_fn, self.inList[i], self.codec, self.alpha,
                self.frameRate
            )  # Any other args, kwargs are passed to the run function
            worker.signals.result.connect(self.print_output)

            #worker.signals.progress.connect(self.progress_fn)
            worker.signals.progress.connect(self.pbList[i].setValue)
            #worker.signals.errorFFMPEG.connect(lambda n: self.errorPB(n,self.pbList[i]))
            worker.signals.errorFFMPEG.connect(self.errorPB)
            worker.signals.finished.connect(self.thread_complete)

            #This sort of worked, lambda function evals at the time of error not at the time of assignment
            #so the i is not the actual i of the erroring signal
            #worker.signals.error.connect(lambda n: self.errorPB(n,self.pbList[i]))#,self.tempPB.setFormat))

            # Execute
            self.threadpool.start(worker)
Exemple #31
0
 def downloadAlbumCover(self, artist, album):
     d = CoverRunnable(self, artist, album, qtype="artist")
     QThreadPool.globalInstance().start(d)
Exemple #32
0
 class Test(QObject):
     threadPool = QThreadPool()
     message = pyqtSignal(str, int)
Exemple #33
0
class Ui(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self) # Call the inherited classes __init__ method
        # uic.loadUi('gui/ui/MA35D1-Writer.ui', self) # Load the .ui file

        self.setupUi(self)


        self.setWindowTitle("MA35D1 NuWriter")

        self.addMedia()

        self.text_browser = QtWidgets.QTextBrowser(self)
        self.verticalLayout.addWidget(self.text_browser)

        # Install the custom output stream
        # sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
        self.outputStream = EmittingStream(textWritten=self.normalOutputWritten)
        sys.stdout = self.outputStream
        sys.stderr = self.outputStream

        self.initToolSetting()

        # Attach
        self.browseDDR_btn.clicked.connect(self.iniBrowse)
        self.attach_btn.clicked.connect(self.doAttach)

        self.threadpool = QThreadPool()
    def addMedia(self):

        # DEV_DDR_SRAM = 0
        self.ddrPage = MediaPage(DEV_DDR_SRAM, self)
        self.tabMedia.addTab(self.ddrPage, "DDR/SRAM")

        # DEV_NAND = 1
        self.nandPage = MediaPage(DEV_NAND, self)
        self.tabMedia.addTab(self.nandPage, "NAND")

        # DEV_SD_EMMC = 2
        self.sdEmmcPage = MediaPage(DEV_SD_EMMC, self)
        self.tabMedia.addTab(self.sdEmmcPage, "SD/EMMC")

        # DEV_SPINOR = 3
        self.spiNorPage = MediaPage(DEV_SPINOR, self)
        self.tabMedia.addTab(self.spiNorPage, "SPI NOR")

        # DEV_SPINAND = 4
        self.spiNandPage = MediaPage(DEV_SPINAND, self)
        self.tabMedia.addTab(self.spiNandPage, "SPI NAND")

        # DEV_OTP = 6


    def __del__(self):
        # Restore sys.stdout
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

    ################################################################################################
    # 'MA35D1.ini'
    ################################################################################################

    def initToolSetting(self):

        self.iniFileName = 'MA35D1.ini'

        iniFileName = self.iniFileName

        # https://pyinstaller.readthedocs.io/en/stable/runtime-information.html
        if getattr(sys, 'frozen', False):
            # we are running in a bundle
            app_dir = os.path.dirname(os.path.abspath(sys.executable))
        else:
            # we are running in a normal Python environment
            app_dir = os.path.dirname(os.path.abspath(__file__))

        iniFilePath = os.path.join(app_dir, iniFileName)

        if not os.path.exists(iniFilePath):
            open(iniFilePath, 'w', encoding='utf-8')

        self.conf = configparser.ConfigParser()
        self.conf.read(iniFilePath, encoding='utf-8')

        self.iniFilePath = iniFilePath

        if not self.conf.has_section('Attach'):
            self.conf.add_section('Attach')

        self.ddrFileLineEdit.setText(self.conf.get('Attach', 'Ini File', fallback=''))

        sections = ['DDR', 'NAND', 'SD', 'SPINOR', 'SPINAND', 'OTP', 'USBH']

        for section in sections:
            if not self.conf.has_section(section):
                self.conf.add_section(section)

            if section == 'DDR':
                page = self.ddrPage
            elif section == 'NAND':
                page = self.nandPage
            elif section == 'SD':
                page = self.sdEmmcPage
            elif section == 'SPINOR':
                page = self.spiNorPage
            elif section == 'SPINAND':
                page = self.spiNandPage
            else:
                # print(f'{section} is not supported yet')
                continue

            page.imgPathLine.setText(self.conf.get(section, 'write file', fallback=''))
            page.imgAddress.setText(self.conf.get(section, 'write addr', fallback=''))

            try:
                page.radioPack.setChecked(self.conf.getboolean(section, 'write pack', fallback=False))
            except:

                if section != 'DDR':
                    print(f'fail to set pack in {section}')

                pass

            option = self.conf.get(section, 'write option', fallback='')

            try:
                if option == "Verify":
                    page.verifyWrite.setChecked(True)
                elif option == "Raw":
                    page.rawWrite.setChecked(True)
                elif option == "Execute":
                    page.optExecute.setChecked(True)
                elif option != '' and option != 'None':
                    print(f'unknown optioin {option}')
            except:
                print(f'fail to set optioin {option} in {section}')
                pass

            page.fileSave.setText(self.conf.get(section, 'read file', fallback=''))
            page.readStart.setText(self.conf.get(section, 'read start', fallback=''))
            page.readEnd.setText(self.conf.get(section, 'read length', fallback=''))

            option = self.conf.get(section, 'read option', fallback='')

            try:
                if option == "WithBad":
                    page.readWithBad.setChecked(True)
                elif option != '' and option != 'None':
                    print(f'unknown optioin {option}')
            except:
                print(f'fail to set optioin {option} in {section}')
                pass

            if section == 'DDR':
                continue

            if section == 'SD':
                page.reservedSize.setText(self.conf.get(section, 'storage size', fallback=''))
                page.optEject.setChecked(self.conf.get(section, 'storage option', fallback='') == 'Eject')
            else:
                page.eraseStart.setText(self.conf.get(section, 'erase start', fallback=''))
                page.eraseEnd.setText(self.conf.get(section, 'erase length', fallback=''))
                page.eraseAll.setChecked(self.conf.getboolean(section, 'erase all', fallback=False))

    # def closeEvent(self, evt):
    #     pass

    def normalOutputWritten(self, text):
        """Append text to the QTextEdit."""
        # Maybe QTextEdit.append() works as well, but this is how I do it:
        self.text_browser.insertPlainText(text)
        self.text_browser.moveCursor(QtGui.QTextCursor.End)

    def iniBrowse(self):
        filename = ""
        # Fix for crash in X on Ubuntu 14.04
        filename, _ = QtWidgets.QFileDialog.getOpenFileName()
        if filename != "":
            self.ddrFileLineEdit.setText(filename)

    ################################################################################################
    # command line
    ################################################################################################

    @QtCore.pyqtSlot()
    def doAttach(self):
        iniFile = self.ddrFileLineEdit.text()
        self.conf.set('Attach', 'Ini File', iniFile)
        self.conf.write(open(self.iniFilePath, 'w', encoding='utf-8'))

        self.text_browser.clear()
        # print(f'do_attach({iniFile})')

        # do_attach(iniFile)
        worker = Worker(do_attach, iniFile)

        # Execute
        self.threadpool.start(worker)

    # def do_img_read(media, start, out_file_name, length=0x1, option=OPT_NONE) -> None:
    @QtCore.pyqtSlot(int, str, str, str, int, bool)
    def doImgRead(self, media, startStr, fileStr, lengthStr, option, isall=False):

        if isall:
            start = 0
            length = 0
        else:
            try:
                start = int(startStr, 0) & 0xffffffff
            except:
                start = 0

            try:
                length = int(lengthStr, 0) & 0xffffffff
            except:
                length = 0x1


        self.text_browser.clear()

        if media in [DEV_DDR_SRAM, DEV_NAND, DEV_SPINOR, DEV_SPINAND, DEV_SD_EMMC]:

            if media == DEV_DDR_SRAM:
                section = 'DDR'
            elif media == DEV_NAND:
                section = 'NAND'
            elif media == DEV_SPINOR:
                section = 'SPINOR'
            elif media == DEV_SPINAND:
                section = 'SPINAND'
            else:
                section = 'SD'

            self.conf.set(section, 'read file', fileStr)
            self.conf.set(section, 'read start', startStr)
            self.conf.set(section, 'read length', lengthStr)

            if option == OPT_NONE:
                self.conf.set(section, 'read option', "None")
            elif option == OPT_WITHBAD:
                self.conf.set(section, 'read option', "WithBad")

            if isall:
                self.conf.set(section, 'read all', 'true')
            else:
                self.conf.set(section, 'read all', 'false')

        self.conf.write(open(self.iniFilePath, 'w', encoding='utf-8'))

        # print(f'do_img_read({media}, {start}, {fileStr}, {length}, {option})')
        # do_img_read(media, start, fileStr, length, option)
        worker = Worker(do_img_read, media, start, fileStr, length, option)

        # Execute
        self.threadpool.start(worker)

    # def do_img_program(media, start, image_file_name, option=OPT_NONE) -> None:
    @QtCore.pyqtSlot(int, str, str, int, bool)
    def doImgProgram(self, media, startStr, image_file_name, option, ispack=False):

        try:
            start = int(startStr, 0) & 0xffffffff
        except:
            start = 0

        self.text_browser.clear()

        if media == DEV_DDR_SRAM:
            section = 'DDR'
            self.conf.set(section, 'write file', image_file_name)
            self.conf.set(section, 'write addr', startStr)
            if option == 0:
                self.conf.set(section, 'write option', "None")
            elif option == 2:
                self.conf.set(section, 'write option', "Execute")

        elif media in [DEV_NAND, DEV_SPINOR, DEV_SPINAND, DEV_SD_EMMC]:

            if media == DEV_NAND:
                section = 'NAND'
            elif media == DEV_SPINOR:
                section = 'SPINOR'
            elif media == DEV_SPINAND:
                section = 'SPINAND'
            else:
                section = 'SD'

            self.conf.set(section, 'write file', image_file_name)
            self.conf.set(section, 'write addr', startStr)

            if ispack:
                self.conf.set(section, 'write pack', 'true')
            else:
                self.conf.set(section, 'write pack', 'false')

        elif media == DEV_OTP:
            section = 'OTP'
            self.conf.set(section, 'write file', image_file_name)

        if option == OPT_NONE:
            self.conf.set(section, 'write option', "None")
        elif option == OPT_VERIFY:
            self.conf.set(section, 'write option', "Verify")
        elif option == OPT_RAW:
            self.conf.set(section, 'write option', "Raw")

        self.conf.write(open(self.iniFilePath, 'w', encoding='utf-8'))

        if media == DEV_OTP:
            # print(f'do_otp_program({image_file_name})')
            # do_otp_program(image_file_name)
            worker = Worker(do_otp_program, image_file_name)
        elif ispack:
            # print(f'do_pack_program({media}, {image_file_name}, {option})')
            # do_pack_program(media, image_file_name, option)
            worker = Worker(do_pack_program, media, image_file_name, option)
        else:
            # print(f'do_img_program({media}, {start}, {image_file_name}, {option})')
            # do_img_program(media, start, image_file_name, option)
            worker = Worker(do_img_program, media, start, image_file_name, option)

        # Execute
        self.threadpool.start(worker)


    # def do_img_erase(media, start, length=0, option=OPT_NONE) -> None:
    @QtCore.pyqtSlot(int, str, str, int, bool)
    def doImgErase(self, media, startStr, lengthStr, option, isall=False):

        if isall:
            start = 0
            length = 0
        else:
            try:
                start = int(startStr, 0) & 0xffffffff
            except:
                start = 0

            try:
                length = int(lengthStr, 0) & 0xffffffff
            except:
                length = 0x1


        self.text_browser.clear()

        if media in [DEV_NAND, DEV_SPINOR, DEV_SPINAND, DEV_SD_EMMC]:

            if media == DEV_NAND:
                section = 'NAND'
            elif media == DEV_SPINOR:
                section = 'SPINOR'
            elif media == DEV_SPINAND:
                section = 'SPINAND'
            else:
                section = 'SD'

            self.conf.set(section, 'erase start', startStr)
            self.conf.set(section, 'erase length', lengthStr)

            if isall:
                self.conf.set(section, 'erase all', 'true')
            else:
                self.conf.set(section, 'erase all', 'false')

        self.conf.write(open(self.iniFilePath, 'w', encoding='utf-8'))

        # print(f'do_img_erase({media}, {start}, {length}, {option})')
        # do_img_erase(media, start, length, option)

        worker = Worker(do_img_erase, media, start, length, option)

        # Execute
        self.threadpool.start(worker)

    @QtCore.pyqtSlot(str, int)
    def doMsc(self, reserveStr, option):

        try:
            reserve = int(reserveStr, 0) & 0xffffffff
        except:
            reserve = 0

        self.text_browser.clear()

        section = 'SD'

        if option == OPT_EJECT:
            self.conf.set(section, 'storage option', "Eject")
            reserve = 0
        else:
            self.conf.set(section, 'storage option', "None")
            self.conf.set(section, 'storage size', reserveStr)


        self.conf.write(open(self.iniFilePath, 'w', encoding='utf-8'))

        media = DEV_SD_EMMC
        # print(f'do_msc({media}, {reserve}, {option})')
        # do_msc(media, reserve, option)

        worker = Worker(do_msc, media, reserve, option)

        # Execute
        self.threadpool.start(worker)
Exemple #34
0
 def loadConf(self):
     confWorker=load_conf()
     confWorker.signals.hasConf.connect(self.storeConf)
     confWorker.signals.hasError.connect(lambda x:print(x))
     QThreadPool.globalInstance().start(confWorker)
Exemple #35
0
 def __init__(self):
     super().__init__()
     self.pool = QThreadPool()
     self.pool.globalInstance()
     self.pool.setMaxThreadCount(3)
Exemple #36
0
 def loadTimerConf(self):
     print("loading Timer")
     loadConf=load_conf(config="timer.json")
     loadConf.signals.hasConf_d.connect(self.storeTimerConf)
     loadConf.signals.hasError.connect(logging.error)
     QThreadPool.globalInstance().start(loadConf)
Exemple #37
0
class MainWindow(QWidget):
    
	def __init__(self, inList):
		super().__init__()
		self.inList = inList
		self.nameFrom = 'Folder'
		self.codec = 'utvideo'
		self.alpha = False
		self.frameRate = 24
		self.defaulStyle = ''
		self.okIcon = QIcon(self.style().standardIcon(QStyle.SP_CustomBase))
		self.okPix = QPixmap(self.okIcon.pixmap(QSize(13, 13)))
		self.goodIcon = QIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton))
		self.goodPix = QPixmap(self.goodIcon.pixmap(QSize(13, 13)))
		self.badIcon = QIcon(self.style().standardIcon(QStyle.SP_MessageBoxCritical))
		self.badPix = QPixmap(self.badIcon.pixmap(QSize(13, 13)))
		self.processingIcon = QIcon(self.style().standardIcon(QStyle.SP_ArrowRight))
		self.processingPix = QPixmap(self.processingIcon.pixmap(QSize(13, 13)))
		self.removeIcon = QIcon(self.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
		self.removePix = QPixmap(self.removeIcon.pixmap(QSize(19, 19)))
		self.pbList = []
		self.chList = []
		self.lblList = []
		self.rmbList = []
		#self.newFolders = []
		self.initUI()

	def initUI(self):
		self.resize(653, 476)
		self.setWindowTitle('FFMpeg Python Compressor')
		self.verticalLayout = QVBoxLayout(self)
		self.verticalLayout.setContentsMargins(11, 11, 11, 11)
		self.verticalLayout.setSpacing(11)
		
		#COMBOBOX LABELS
		self.gridLayoutControlls = QGridLayout()
		self.codecLabel = QLabel('Codec', self)
		self.alphaLabel = QLabel('Alpha' , self)
		self.frameRateLabel = QLabel('Frame Rate' , self)
		self.gridLayoutControlls.addWidget(self.codecLabel, 0, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaLabel, 0, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateLabel, 0, 2, 1, 1)
		
		#COMBOBOXES AND COMPRESS BUTTON
		self.codecComboBox = QComboBox(self)
		self.codecComboBox.setMinimumWidth(80)
		self.codecComboBox.addItem("UT Video")
		self.codecComboBox.activated[str].connect(self.chooseCodec)
		
		self.alphaComboBox = QComboBox(self)
		self.alphaComboBox.setMinimumWidth(80)
		self.alphaComboBox.addItem("No Alpha")
		self.alphaComboBox.addItem("with Alpha")
		self.alphaComboBox.activated[str].connect(self.chooseAlpha)
		
		self.frameRateComboBox = QComboBox(self)
		self.frameRateComboBox.setMinimumWidth(80)
		self.frameRateComboBox.addItem("24.00")
		self.frameRateComboBox.addItem("30.00")
		self.frameRateComboBox.activated[str].connect(self.chooseFrameRate)
		
		self.compressButton = QPushButton('Compress', self)
		self.compressButton.clicked[bool].connect(self.compressPress)
			
		self.gridLayoutControlls.addWidget(self.codecComboBox, 1, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaComboBox, 1, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateComboBox, 1, 2, 1, 1)
		self.gridLayoutControlls.addWidget(self.compressButton, 1, 3, 1, 1)
			
		#RADIO BUTTON GROUP
		self.groupBox = QButtonGroup(self)
		self.radio1 = QRadioButton('Output file name from Folder name', self)
		self.radio2 = QRadioButton('Output file name from File name', self)
		self.radio1.setChecked(True)
		self.groupBox.addButton(self.radio1,1)
		self.groupBox.addButton(self.radio2,2)
		self.groupBox.buttonClicked[int].connect(self.radioBtnState)
		
		self.gridLayoutControlls.addWidget(self.radio1, 2, 0, 1, 2)
		self.gridLayoutControlls.addWidget(self.radio2, 2, 2, 1, 2)
		
		#LINE
		self.line = QFrame(self)
		self.line.setLineWidth(2)
		self.line.setFrameShape(QFrame.HLine)
		self.line.setFrameShadow(QFrame.Sunken)
		
		self.gridLayoutControlls.addWidget(self.line, 3, 0, 1, 4)
		
		#PROGRESS BAR 
		self.gridLayoutProgress = QGridLayout()
		self.gridLayoutProgress.setSizeConstraint(QLayout.SetNoConstraint)
		
		self.removeGroupBox = QButtonGroup(self)
		for i in range(len(self.inList)):
			self.tempCheckBox = QCheckBox(self)
			self.tempCheckBox.setChecked(True)
			
			self.tempRemoveButton = QPushButton(self)
			self.tempRemoveButton.setIcon(self.removeIcon)
			self.tempRemoveButton.setFlat(True)
			self.tempRemoveButton.setIconSize(QSize(19,19))
			self.tempRemoveButton.setFixedSize(QSize(21,21))
			
			
			self.tempPB = QProgressBar(self)
			self.tempPB.setMinimum(0)
			self.tempPB.setMaximum(100)
			self.tempPB.setTextVisible(True)
			self.tempPB.setFormat(str(self.inList[i])+" %p%")
			self.tempPB.setAlignment(Qt.AlignCenter)
			self.tempPB.setValue(0)
			if i==0:
				self.defaulStyle = self.tempPB.styleSheet()
			
			self.tempStatusLabel = QLabel(self)			
			self.tempStatusLabel.setPixmap(self.okPix)
			
			self.gridLayoutProgress.addWidget(self.tempCheckBox, i, 0, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempPB, i, 1, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempStatusLabel, i, 2, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempRemoveButton, i, 3, 1, 1)
			self.removeGroupBox.addButton(self.tempRemoveButton,i)
			
			self.pbList.append(self.tempPB)
			self.chList.append(self.tempCheckBox)
			self.lblList.append(self.tempStatusLabel)
			self.rmbList.append(self.tempRemoveButton)
			
		self.removeGroupBox.buttonClicked[int].connect(self.removeButtonClicked)

		#ADD MORE AREA
		self.gridLayoutAddMore = QGridLayout()
		self.gridLayoutAddMore.setContentsMargins(0, 0, 0, 0)
		self.dragAndDropLabel = QLabel("Drag and Drop more folders here", self)
		self.dragAndDropLabel.setMinimumSize(QSize(0, 40))
		self.dragAndDropLabel.setAlignment(Qt.AlignCenter)
		self.gridLayoutAddMore.addWidget(self.dragAndDropLabel, 1, 0, 1, 1)
		
		#DEBUG AREA
		self.gridLayoutDebug = QGridLayout()
		self.line_2 = QFrame(self)
		self.line_2.setLineWidth(2)
		self.line_2.setFrameShape(QFrame.HLine)
		self.line_2.setFrameShadow(QFrame.Sunken)
		
		self.debugLabel = QLabel('Debug:',self)
		self.debugLabel.setMinimumSize(QSize(0, 20))
		self.debugLabel.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
		
		self.errorText = QPlainTextEdit('',self)
		self.errorText.setReadOnly(True)
		
		self.gridLayoutDebug.addWidget(self.line_2, 0, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.debugLabel, 1, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.errorText, 2, 0, 1, 1)
		
		self.verticalLayout.addLayout(self.gridLayoutControlls)
		self.verticalLayout.addLayout(self.gridLayoutProgress)
		self.verticalLayout.addLayout(self.gridLayoutAddMore)
		self.verticalLayout.addLayout(self.gridLayoutDebug)
		
		# Enable dragging and dropping onto the GUI
		self.setAcceptDrops(True)
		
		#QtCore.QMetaObject.connectSlotsByName(self)
		self.show()
        
		self.threadpool = QThreadPool()
		self.threadpool.setMaxThreadCount(1)
		print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
    
	
	'''
	Drag+Drop Functions
	'''
	# The following three methods set up dragging and dropping for the app
	def dragEnterEvent(self, e):
		if e.mimeData().hasUrls:
			e.accept()
		else:
			e.ignore()

	def dragMoveEvent(self, e):
		if e.mimeData().hasUrls:
			e.accept()
		else:
			e.ignore()

	def dropEvent(self, e):
		"""
		Drop files directly onto the widget
		File locations are stored in fname
		:param e:
		:return:
		"""
		newFolders = []
		if e.mimeData().hasUrls:
			e.setDropAction(Qt.CopyAction)
			e.accept()
			# Workaround for OSx dragging and dropping
			for url in e.mimeData().urls():
				if op_sys == 'Darwin':
					#check for dir here as well
					fname = str(NSURL.URLWithString_(str(url.toString())).filePathURL().path())
				else:
					fname = str(url.toLocalFile())
					if os.path.isdir(fname) == True:
						newFolders.append(fname)
					#print(fname)

			#self.fname = fname
			#print(self.fname)
			#self.load_image()
			self.addNewFolders(newFolders)
			self.inList = self.inList + newFolders
		else:
			e.ignore()
	
	#rewrite as a def here and at the init function
	def addNewFolders(self, newFolders):
		pbCount = len(self.pbList)
		for i in range(len(newFolders)):
			self.tempCheckBox = QCheckBox(self)
			self.tempCheckBox.setChecked(True)
			
			self.tempPB = QProgressBar(self)
			self.tempPB.setMinimum(0)
			self.tempPB.setMaximum(100)
			self.tempPB.setTextVisible(True)
			self.tempPB.setFormat(str(newFolders[i])+" %p%")
			self.tempPB.setAlignment(Qt.AlignCenter)
			self.tempPB.setValue(0)

			self.tempStatusLabel = QLabel(self)			
			self.tempStatusLabel.setPixmap(self.okPix)
			
			self.gridLayoutProgress.addWidget(self.tempCheckBox, pbCount+i, 0, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempPB, pbCount+i, 1, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempStatusLabel, pbCount+i, 2, 1, 1)
			
			self.pbList.append(self.tempPB)
			self.chList.append(self.tempCheckBox)
			self.lblList.append(self.tempStatusLabel)
	
	
	'''
	Button Functions
	'''
	def chooseAlpha(self, text):
		switcher={
			"No Alpha":False,
			"with Alpha":True
		}
		self.alpha = switcher.get(text,"Invalid day of week")
		#print (self.alpha)

	def chooseCodec(self, text):
		switcher={
			"UT Video":"utvideo"
		}
		self.codec =  switcher.get(text,"Invalid day of week")
		#print (self.codec)
		
	def chooseFrameRate(self, text):
		self.frameRate =  float(text)
		#print (self.frameRate)
	
	
	def currentData(self, widget):
		return widget.currentText() 

	def radioBtnState(self, text):
		switcher={
			1:'Folder',
			2:'File'
		}
		self.nameFrom = switcher.get(text,"Invalid day of week")
		#print(self.nameFrom)
	
	def removeButtonClicked(self, i):
		#print('remove trigger on id '+str(i))
		
		#self.pbList.pop(i)
		self.pbList[i].hide()
		self.chList[i].setChecked(False)
		self.chList[i].hide()
		self.lblList[i].hide()
		self.rmbList[i].hide()
		
		self.removeGroupBox.removeButton(self.rmbList[i])
		self.gridLayoutProgress.removeWidget(self.pbList[i])
		self.gridLayoutProgress.removeWidget(self.chList[i])
		self.gridLayoutProgress.removeWidget(self.lblList[i])
		self.gridLayoutProgress.removeWidget(self.rmbList[i])
		
		'''
		print(self.pbList)
		print(self.chList)
		print(self.lblList)
		print(self.rmbList)
		'''
		
		self.pbList.pop(i)
		self.chList.pop(i)
		self.lblList.pop(i)
		self.rmbList.pop(i)
		self.inList.pop(i)		
		
		for j in range(len(self.removeGroupBox.buttons())):
			button = self.removeGroupBox.buttons()[j]
			#print(button)
			#print('original id '+str(self.removeGroupBox.id(button)))
			#print('new id '+str(j))
			self.removeGroupBox.setId(button,j)
		
	'''
	Execution Functions
	'''
	def execute_this_fn(self, path, codec, alpha, frameRate, nameFrom, i, progress_callback, errorFFMPEG_callback):
		#print(path)
		pyCompression = pyFFMEGCompress(path, codec, alpha, frameRate, nameFrom)
		ffProcess = pyCompression.ffmpegCompress()
		self.lblList[i].setPixmap(self.processingPix)
		
		#with kwargs
		kwargs = {'progress_callback':progress_callback, 'errorFFMPEG_callback':errorFFMPEG_callback}
		pyCompression.printProcess(ffProcess, **kwargs)

		return (pyCompression.debugString,pyCompression.error,i)
 
	def printOutput(self, s):
		print("Printing output "+ str(s))
		
	def threadComplete(self, r):
		#print("THREAD COMPLETE! WITH ERROR " + str(r[2]) )
		if r[1]==False:
			self.lblList[r[2]].setPixmap(self.goodPix)
			self.pbList[r[2]].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #44dd14,stop: 0.4999 #39c10f,stop: 0.5 #39c10f,stop: 1 #39c10f );border-radius: 3px; border: 1px solid #29880b;}QProgressBar{color:white}")

	def errorPB(self, err):
		for i in range(len(self.pbList)):
			if self.pbList[i].format() == err:
				self.pbList[i].setValue(100)
				self.pbList[i].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 );border-radius: 3px; border: 1px solid #a60233;}QProgressBar{color:white}")
				self.pbList[i].setFormat(self.pbList[i].format()+" - Error")
				self.chList[i].setChecked(False)
				self.lblList[i].setPixmap(self.badPix)
				
	def resetProgressBar(self, pb, text, lbl):
		pb.setValue(0)
		pb.setFormat(text + ' %p%')
		pb.setStyleSheet(self.defaulStyle)
		lbl.setPixmap(self.okPix)
	

	def compressPress(self):
		for i in range(len(self.pbList)):				
			if self.chList[i].isChecked():
				self.resetProgressBar(self.pbList[i],self.inList[i],self.lblList[i])
				
				worker = Worker(self.execute_this_fn, self.inList[i], self.codec, self.alpha, self.frameRate, self.nameFrom, i) # Any other args, kwargs are passed to the run function
				#worker.signals.result.connect(self.printOutput)
				worker.signals.result.connect(self.errorText.appendPlainText)
				worker.signals.progress.connect(self.pbList[i].setValue)
				worker.signals.errorFFMPEG.connect(self.errorPB)
				worker.signals.error.connect(self.errorPB)
				worker.signals.finished.connect(self.threadComplete)
				#worker.signals.finished.connect(self.errorText.appendPlainText)
				
				# Execute
				self.threadpool.start(worker)
Exemple #38
0
class K2001A_TEST_dialog(QDialog):
    def __init__(self, parent):
        super().__init__(parent)

        # Initial read of the config file
        self.config = configparser.ConfigParser()

        try:
            self.config.read('config.ini')
            self.last_used_scan = self.config.get('LastScan', 'last_used_scan')

            self.schroll_pts = int(
                self.config.get(self.last_used_scan, 'schroll'))
            self.k2001aport = self.config.get(
                "Instruments", 'k2001aport').strip().split(',')[0]
        except configparser.NoOptionError as e:
            QMessageBox.critical(
                self, 'Message', ''.join(
                    ["Main FAULT while reading the config.ini file\n",
                     str(e)]))
            raise

        self.setupUi()

    def setupUi(self):

        serialport = QLabel("GPIB port", self)
        self.serialportEdit = QLineEdit(self.k2001aport, self)

        self.runstopButton = QPushButton("START", self)
        self.clearButton = QPushButton("Clear", self)

        schroll_lbl = QLabel("Schroll elapsed time ", self)
        self.combo0 = QComboBox(self)
        mylist0 = ["100", "200", "400", "600", "800", "1000", "1500", "2000"]
        self.combo0.addItems(mylist0)
        self.combo0.setCurrentIndex(mylist0.index(str(self.schroll_pts)))

        ##############################################

        g0_1 = QGridLayout()
        g0_1.addWidget(serialport, 0, 0)
        g0_1.addWidget(self.serialportEdit, 0, 1)
        g0_1.addWidget(schroll_lbl, 0, 2)
        g0_1.addWidget(self.combo0, 0, 3)
        g0_1.addWidget(self.runstopButton, 0, 4)
        g0_1.addWidget(self.clearButton, 0, 5)

        ##############################################

        # set graph  and toolbar to a new vertical group vcan
        self.pw1 = pg.PlotWidget()

        ##############################################

        # create table
        self.tableWidget = self.createTable()

        ##############################################

        # SET ALL VERTICAL COLUMNS TOGETHER
        vbox = QVBoxLayout()
        vbox.addLayout(g0_1)
        vbox.addWidget(self.pw1)

        hbox = QHBoxLayout()
        hbox.addLayout(vbox)
        hbox.addWidget(self.tableWidget)

        self.threadpool = QThreadPool()
        print("Multithreading in the K2001A with maximum %d threads" %
              self.threadpool.maxThreadCount())
        self.isRunning = False

        self.setLayout(hbox)
        self.setWindowTitle("Test Keithley 2001A")

        # PLOT 2 settings
        # create plot and add it to the figure canvas
        self.p1 = self.pw1.plotItem
        self.curve1 = self.p1.plot(pen='w')
        # create plot and add it to the figure
        self.p0_1 = pg.ViewBox()
        self.curve2 = pg.PlotCurveItem(pen='r')
        self.p0_1.addItem(self.curve2)
        # connect respective axes to the plot
        #self.p1.showAxis('left')
        self.p1.getAxis('left').setLabel("Voltage", units="V", color='yellow')
        self.p1.showAxis('right')
        self.p1.getAxis('right').setLabel("Arb unit, 1023=1.1V",
                                          units="",
                                          color='red')
        self.p1.scene().addItem(self.p0_1)
        self.p1.getAxis('right').linkToView(self.p0_1)
        self.p0_1.setXLink(self.p1)

        self.p1.getAxis('bottom').setLabel("Points", units="", color='yellow')
        # Use automatic downsampling and clipping to reduce the drawing load
        self.pw1.setDownsampling(mode='peak')
        self.pw1.setClipToView(True)

        # Initialize and set titles and axis names for both plots
        self.clear_vars_graphs()
        self.combo0.activated[str].connect(self.onActivated0)

        # run or cancel the main script
        self.runstopButton.clicked.connect(self.runstop)
        self.clearButton.clicked.connect(self.set_clear)
        self.clearButton.setEnabled(False)

    def onActivated0(self, text):

        old_st = self.schroll_pts

        self.schroll_pts = int(str(text))

        if old_st > self.schroll_pts:
            self.set_clear()

    def createTable(self):

        tableWidget = QTableWidget()

        # set row count
        #tableWidget.setRowCount(20)

        # set column count
        tableWidget.setColumnCount(2)

        # hide grid
        tableWidget.setShowGrid(False)

        # hide vertical header
        vh = tableWidget.verticalHeader()
        vh.setVisible(False)

        # set the font
        font = QFont("Courier New", 9)
        tableWidget.setFont(font)
        tableWidget.setStyleSheet("color: blue")

        # place content into individual table fields
        #tableWidget.setItem(0,0, QTableWidgetItem("abe"))

        tableWidget.setHorizontalHeaderLabels(["Point no.", "U[V]"])
        #tableWidget.setVerticalHeaderLabels(["aa","bb","cc","dd"])

        # set horizontal header properties
        hh = tableWidget.horizontalHeader()
        hh.setStretchLastSection(True)

        # set column width to fit contents
        tableWidget.resizeColumnsToContents()

        # enable sorting
        #tableWidget.setSortingEnabled(True)

        return tableWidget

    def set_cancel(self):

        self.worker.abort()

        self.clearButton.setEnabled(True)
        self.runstopButton.setText("START")

    def set_clear(self):

        self.clear_vars_graphs()
        self.clearButton.setEnabled(False)
        self.clearButton.setText("Cleared")

    def runstop(self):

        sender = self.sender()

        if sender.text() == "START":
            self.set_run()
        elif sender.text() == "STOP":
            self.set_cancel()

    def set_run(self):

        try:
            self.K2001A = K2001A.K2001A(str(self.serialportEdit.text()), False)
            rm = visa.ResourceManager()
            print(rm.list_resources())
        except Exception as e:
            reply = QMessageBox.critical(
                self, 'Keithley 2001A TEST MODE', ''.join([
                    "K2001A could not return valid echo signal. Check the port name and check the connection.\n",
                    str(e),
                    "\n\nShould the program proceeds into the TEST MODE?"
                ]), QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.K2001A = K2001A.K2001A(str(self.serialportEdit.text()),
                                            True)
            else:
                return

        self.runstopButton.setEnabled(True)
        self.runstopButton.setText("STOP")

        self.clearButton.setEnabled(False)
        self.combo0.setEnabled(False)
        self.serialportEdit.setEnabled(False)
        self.isRunning = True

        setrun_obj = type('setscan_obj', (object, ), {'k2001a': self.K2001A})

        self.worker = K2001A_Worker(setrun_obj)
        self.worker.signals.update0.connect(self.update0)
        self.worker.signals.finished.connect(self.finished)

        # Execute
        self.threadpool.start(self.worker)

    def update0(self, volts):

        self.tal += 1

        # set row height
        self.tableWidget.setRowCount(self.tal + 1)
        self.tableWidget.setRowHeight(self.tal, 12)

        # add row elements
        self.tableWidget.setItem(self.tal, 0, QTableWidgetItem(str(self.tal)))
        self.tableWidget.setItem(self.tal, 1, QTableWidgetItem(str(volts)))

        if len(self.tals) > self.schroll_pts:
            self.tals[:-1] = self.tals[
                1:]  # shift data in the array one sample left
            self.tals[-1] = self.tal
            self.plot_as_tr[:-1] = self.plot_as_tr[
                1:]  # shift data in the array one sample left
            self.plot_as_tr[-1] = volts
            #self.plot_time_tr[:-1] = self.plot_time_tr[1:]  # shift data in the array one sample left
            #self.plot_time_tr[-1] = timelist
            self.plot_volts_tr[:-1] = self.plot_volts_tr[
                1:]  # shift data in the array one sample left
            self.plot_volts_tr[-1] = volts
        else:
            self.tals.extend([self.tal])
            self.plot_as_tr.extend([volts])
            self.plot_volts_tr.extend([volts])
            #self.plot_time_tr.extend([ timelist ])

        ## Handle view resizing
        def updateViews():
            ## view has resized; update auxiliary views to match
            self.p0_1.setGeometry(self.p1.vb.sceneBoundingRect())
            #p3.setGeometry(p1.vb.sceneBoundingRect())

            ## need to re-update linked axes since this was called
            ## incorrectly while views had different shapes.
            ## (probably this should be handled in ViewBox.resizeEvent)
            self.p0_1.linkedViewChanged(self.p1.vb, self.p0_1.XAxis)
            #p3.linkedViewChanged(p1.vb, p3.XAxis)

        updateViews()
        self.p1.vb.sigResized.connect(updateViews)

        self.curve1.setData(self.tals, self.plot_as_tr)
        self.curve2.setData(self.tals, self.plot_volts_tr)

    def finished(self):
        self.isRunning = False
        self.serialportEdit.setEnabled(True)
        self.combo0.setEnabled(True)
        self.clearButton.setEnabled(True)
        self.clearButton.setText("Clear")

    def clear_vars_graphs(self):
        # PLOT 2 initial canvas settings
        self.tal = -1
        self.tals = []
        self.all_time_tr = []
        self.plot_as_tr = []
        self.plot_volts_tr = []
        #self.plot_time_tr=[]
        self.curve1.clear()
        self.curve2.clear()
        self.tableWidget.clearContents()

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Message',
                                     "Quit now? Changes will not be saved!",
                                     QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            if hasattr(self, 'K2001A'):
                if self.isRunning:
                    QMessageBox.warning(
                        self, 'Message',
                        "Run in progress. Cancel the scan then quit!")
                    event.ignore()
                    return

            event.accept()
        else:
            event.ignore()
Exemple #39
0
	def initUI(self):
		self.resize(653, 476)
		self.setWindowTitle('FFMpeg Python Compressor')
		self.verticalLayout = QVBoxLayout(self)
		self.verticalLayout.setContentsMargins(11, 11, 11, 11)
		self.verticalLayout.setSpacing(11)
		
		#COMBOBOX LABELS
		self.gridLayoutControlls = QGridLayout()
		self.codecLabel = QLabel('Codec', self)
		self.alphaLabel = QLabel('Alpha' , self)
		self.frameRateLabel = QLabel('Frame Rate' , self)
		self.gridLayoutControlls.addWidget(self.codecLabel, 0, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaLabel, 0, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateLabel, 0, 2, 1, 1)
		
		#COMBOBOXES AND COMPRESS BUTTON
		self.codecComboBox = QComboBox(self)
		self.codecComboBox.setMinimumWidth(80)
		self.codecComboBox.addItem("UT Video")
		self.codecComboBox.activated[str].connect(self.chooseCodec)
		
		self.alphaComboBox = QComboBox(self)
		self.alphaComboBox.setMinimumWidth(80)
		self.alphaComboBox.addItem("No Alpha")
		self.alphaComboBox.addItem("with Alpha")
		self.alphaComboBox.activated[str].connect(self.chooseAlpha)
		
		self.frameRateComboBox = QComboBox(self)
		self.frameRateComboBox.setMinimumWidth(80)
		self.frameRateComboBox.addItem("24.00")
		self.frameRateComboBox.addItem("30.00")
		self.frameRateComboBox.activated[str].connect(self.chooseFrameRate)
		
		self.compressButton = QPushButton('Compress', self)
		self.compressButton.clicked[bool].connect(self.compressPress)
			
		self.gridLayoutControlls.addWidget(self.codecComboBox, 1, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaComboBox, 1, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateComboBox, 1, 2, 1, 1)
		self.gridLayoutControlls.addWidget(self.compressButton, 1, 3, 1, 1)
			
		#RADIO BUTTON GROUP
		self.groupBox = QButtonGroup(self)
		self.radio1 = QRadioButton('Output file name from Folder name', self)
		self.radio2 = QRadioButton('Output file name from File name', self)
		self.radio1.setChecked(True)
		self.groupBox.addButton(self.radio1,1)
		self.groupBox.addButton(self.radio2,2)
		self.groupBox.buttonClicked[int].connect(self.radioBtnState)
		
		self.gridLayoutControlls.addWidget(self.radio1, 2, 0, 1, 2)
		self.gridLayoutControlls.addWidget(self.radio2, 2, 2, 1, 2)
		
		#LINE
		self.line = QFrame(self)
		self.line.setLineWidth(2)
		self.line.setFrameShape(QFrame.HLine)
		self.line.setFrameShadow(QFrame.Sunken)
		
		self.gridLayoutControlls.addWidget(self.line, 3, 0, 1, 4)
		
		#PROGRESS BAR 
		self.gridLayoutProgress = QGridLayout()
		self.gridLayoutProgress.setSizeConstraint(QLayout.SetNoConstraint)
		
		self.removeGroupBox = QButtonGroup(self)
		for i in range(len(self.inList)):
			self.tempCheckBox = QCheckBox(self)
			self.tempCheckBox.setChecked(True)
			
			self.tempRemoveButton = QPushButton(self)
			self.tempRemoveButton.setIcon(self.removeIcon)
			self.tempRemoveButton.setFlat(True)
			self.tempRemoveButton.setIconSize(QSize(19,19))
			self.tempRemoveButton.setFixedSize(QSize(21,21))
			
			
			self.tempPB = QProgressBar(self)
			self.tempPB.setMinimum(0)
			self.tempPB.setMaximum(100)
			self.tempPB.setTextVisible(True)
			self.tempPB.setFormat(str(self.inList[i])+" %p%")
			self.tempPB.setAlignment(Qt.AlignCenter)
			self.tempPB.setValue(0)
			if i==0:
				self.defaulStyle = self.tempPB.styleSheet()
			
			self.tempStatusLabel = QLabel(self)			
			self.tempStatusLabel.setPixmap(self.okPix)
			
			self.gridLayoutProgress.addWidget(self.tempCheckBox, i, 0, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempPB, i, 1, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempStatusLabel, i, 2, 1, 1)
			self.gridLayoutProgress.addWidget(self.tempRemoveButton, i, 3, 1, 1)
			self.removeGroupBox.addButton(self.tempRemoveButton,i)
			
			self.pbList.append(self.tempPB)
			self.chList.append(self.tempCheckBox)
			self.lblList.append(self.tempStatusLabel)
			self.rmbList.append(self.tempRemoveButton)
			
		self.removeGroupBox.buttonClicked[int].connect(self.removeButtonClicked)

		#ADD MORE AREA
		self.gridLayoutAddMore = QGridLayout()
		self.gridLayoutAddMore.setContentsMargins(0, 0, 0, 0)
		self.dragAndDropLabel = QLabel("Drag and Drop more folders here", self)
		self.dragAndDropLabel.setMinimumSize(QSize(0, 40))
		self.dragAndDropLabel.setAlignment(Qt.AlignCenter)
		self.gridLayoutAddMore.addWidget(self.dragAndDropLabel, 1, 0, 1, 1)
		
		#DEBUG AREA
		self.gridLayoutDebug = QGridLayout()
		self.line_2 = QFrame(self)
		self.line_2.setLineWidth(2)
		self.line_2.setFrameShape(QFrame.HLine)
		self.line_2.setFrameShadow(QFrame.Sunken)
		
		self.debugLabel = QLabel('Debug:',self)
		self.debugLabel.setMinimumSize(QSize(0, 20))
		self.debugLabel.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
		
		self.errorText = QPlainTextEdit('',self)
		self.errorText.setReadOnly(True)
		
		self.gridLayoutDebug.addWidget(self.line_2, 0, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.debugLabel, 1, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.errorText, 2, 0, 1, 1)
		
		self.verticalLayout.addLayout(self.gridLayoutControlls)
		self.verticalLayout.addLayout(self.gridLayoutProgress)
		self.verticalLayout.addLayout(self.gridLayoutAddMore)
		self.verticalLayout.addLayout(self.gridLayoutDebug)
		
		# Enable dragging and dropping onto the GUI
		self.setAcceptDrops(True)
		
		#QtCore.QMetaObject.connectSlotsByName(self)
		self.show()
        
		self.threadpool = QThreadPool()
		self.threadpool.setMaxThreadCount(1)
		print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
Exemple #40
0
class Reset_dialog(QDialog):
    def __init__(self, parent, inst_list):
        super().__init__(parent)

        # constants
        self.inst_list = inst_list

        self.setupUi()

    def setupUi(self):

        self.stopButton = QPushButton("STOP RESET", self)
        self.stopButton.setFixedHeight(35)
        self.stopButton.setFixedWidth(150)
        self.stopButton.setEnabled(False)

        self.startButton = QPushButton("Start reset", self)
        self.startButton.setFixedHeight(35)
        self.startButton.setFixedWidth(150)
        self.startButton.setEnabled(True)

        lbl0 = QLabel("Statusbyte returned from the SMC100PP:\t", self)
        self.lbl_st = QLabel("", self)
        self.lbl_st.setStyleSheet("color: blue")

        grid_0 = QHBoxLayout()
        grid_0.addWidget(self.startButton)
        grid_0.addWidget(self.stopButton)
        grid_1 = QHBoxLayout()
        grid_1.addWidget(lbl0)
        grid_1.addWidget(self.lbl_st)
        grid_2 = QVBoxLayout()
        grid_2.addLayout(grid_0)
        grid_2.addLayout(grid_1)

        # cancel the script run
        self.startButton.clicked.connect(self.start)
        self.stopButton.clicked.connect(self.abort)

        self.threadpool = QThreadPool()

        self.setLayout(grid_2)
        self.setWindowTitle("Reset dialog for SMC100PP stepper")

        # re-adjust/minimize the size of the e-mail dialog
        # depending on the number of attachments
        grid_2.setSizeConstraint(grid_2.SetFixedSize)

    def abort(self):

        self.worker.abort()

    def start(self):

        reply = QMessageBox.question(
            self, 'Message',
            "The stepper will RESET and MOVE to the home position. Remove all components from the stepper head!",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:

            self.worker = Reset_Thread(self.inst_list)
            self.worker.signals.finished.connect(self.finished)
            self.worker.signals.info.connect(self.info)
            self.worker.signals.statusbyte.connect(self.statusbyte)
            # Execute
            self.threadpool.start(self.worker)

            #################################################

            self.startButton.setEnabled(False)
            self.startButton.setText("..reseting..")

    def finished(self):

        self.startButton.setEnabled(True)
        self.startButton.setText("Start reset")
        self.stopButton.setEnabled(False)
        self.setWindowTitle("Reset dialog for SMC100PP stepper")

    def statusbyte(self, sb):

        self.lbl_st.setText(sb)

    def info(self, mystr):

        if mystr == "go_home":
            self.setWindowTitle("homing the stepper, please wait!")
            self.stopButton.setEnabled(True)
        elif mystr == "reset":
            self.setWindowTitle("reseting the stepper, please wait!")
            self.stopButton.setEnabled(False)
        else:
            self.stopButton.setEnabled(False)

    def about(self, mystr):

        QMessageBox.about(self, 'Message', mystr)

    def warning(self, mystr):

        QMessageBox.warning(self, 'Message', mystr)

    def critical(self, mystr):

        QMessageBox.critical(self, 'Message', mystr)

    def closeEvent(self, event):

        event.accept()
    def __init__(self, base):
        QWidget.__init__(self)

        self.base = base

        self.setWindowIcon(QIcon('icon.ico'))
        self.setWindowTitle(TITLE)
        self.setBackgroundColor(Qt.white)

        self.processHeaderWidget = QWidget()
        self.processHeaderLayout = QHBoxLayout(self.processHeaderWidget)
        self.processHeaderLayout.setContentsMargins(0, 0, 0, 0)

        self.processLabel = QLabel('Available processes:')
        self.githubLabel = QLabel('<a href="https://github.com/darktohka/p3dephaser">GitHub</a>')
        self.githubLabel.setOpenExternalLinks(True)

        self.refreshButton = QPushButton('Refresh')
        self.refreshButton.clicked.connect(self.refreshProcesses)
        self.refreshButton.setFixedSize(100, 23)

        self.multifileWidget = QWidget()
        self.multifileLayout = QHBoxLayout(self.multifileWidget)
        self.multifileLayout.setContentsMargins(0, 0, 0, 0)
        self.multifileLabel = QLabel('Requested multifile names:')
        self.multifileBox = QLineEdit(self)
        self.multifileBox.returnPressed.connect(self.beginScan)

        self.multifileLayout.addWidget(self.multifileLabel)
        self.multifileLayout.addWidget(self.multifileBox)

        self.scanButton = QPushButton('Scan')
        self.scanButton.clicked.connect(self.beginScan)

        self.processListBox = QListWidget()

        self.processHeaderLayout.addWidget(self.processLabel)
        self.processHeaderLayout.addStretch(1)
        self.processHeaderLayout.addWidget(self.githubLabel)
        self.processHeaderLayout.addWidget(self.refreshButton)

        self.resultTable = QTableWidget()
        self.resultTable.setColumnCount(3)
        self.resultTable.horizontalHeader().setStretchLastSection(True)
        self.resultTable.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        for i, header in enumerate(('Process', 'Multifile', 'Password')):
            self.resultTable.setHorizontalHeaderItem(i, QTableWidgetItem(header))

        self.baseLayout = QVBoxLayout(self)
        self.baseLayout.setContentsMargins(15, 15, 15, 15)
        self.baseLayout.addWidget(self.processHeaderWidget)
        self.baseLayout.addWidget(self.processListBox)
        self.baseLayout.addWidget(self.multifileWidget)
        self.baseLayout.addWidget(self.scanButton)
        self.baseLayout.addWidget(self.resultTable)

        self.refreshProcesses()

        self.threadPool = QThreadPool()
        self.worker = None
        self.processName = None
        self.nextClick = 0
        self.stopEvent = threading.Event()
class ProgressController:
    current_method = 0
    current_iteration = 0

    _max_iterations: int
    _max_methods: int
    _current_progress = 0

    _thread_pool: QThreadPool
    _ui: Ui_MainWindow
    _time_start: datetime
    _time_current: datetime
    _timer: QTimer
    _interval: int

    def __init__(self, ui):
        self._ui = ui

        self._thread_pool = QThreadPool()
        print("Multithreading with maximum %d threads" % self._thread_pool.maxThreadCount())

        self._max_iterations = 0
        self._max_methods = 0

        self._interval = 1000
        self._timer = QTimer()
        self._timer.setInterval(self._interval)
        self._timer.timeout.connect(self._timer_tick)

    def init_progress(self, progress_fn):
        worker = Worker(progress_fn)
        worker.signals.result.connect(self._print_output)
        worker.signals.finished.connect(self._thread_complete)
        worker.signals.progress.connect(self._update_progress)

        self._thread_pool.start(worker)

    def _print_output(self, s):
        print(s)

    def _thread_complete(self):
        self.stop()
        print("THREAD COMPLETE!")

    def start(self):
        self._reset()
        self._update_progress()
        self._timer.start()

    def _reset(self):
        ProgressController.reset_iteration()
        ProgressController.reset_current_method()
        self._time_start = datetime.datetime.now()
        self._time_current = self._time_start

    def stop(self):
        self._timer.stop()

    def _update_progress(self):
        progress = self._get_progress_percent()
        self._ui.progress_bar.setValue(progress)

        text = self._get_progress_text()
        self._ui.progress_info.setText(text)

    def _get_progress_percent(self):
        total = self._max_methods * self._max_iterations
        progress = (ProgressController.current_method - 1) * self._max_iterations + ProgressController.current_iteration
        return int(progress / total * 100)

    def _get_progress_text(self):
        time_diff = self._time_current - self._time_start
        format_str = "{:d}. Method / {:d} of {:d} Iterations / {:.0f}s"
        text = format_str.format(
            ProgressController.current_method,
            ProgressController.current_iteration,
            self._max_iterations,
            time_diff.total_seconds()
        )
        return text

    def _timer_tick(self):
        self._time_current = datetime.datetime.now()
        self._update_progress()

    def set_max_iterations(self, iterations):
        self._max_iterations = iterations

    @staticmethod
    def inc_iteration():
        ProgressController.current_iteration += 1

    @staticmethod
    def reset_iteration():
        ProgressController.current_iteration = 0

    def set_max_methods(self, max_methods):
        self._max_methods = max_methods

    @staticmethod
    def inc_method_counter():
        ProgressController.current_method += 1

    @staticmethod
    def reset_current_method():
        ProgressController.current_method = 0
class MainWidget(QWidget):

    def __init__(self, base):
        QWidget.__init__(self)

        self.base = base

        self.setWindowIcon(QIcon('icon.ico'))
        self.setWindowTitle(TITLE)
        self.setBackgroundColor(Qt.white)

        self.processHeaderWidget = QWidget()
        self.processHeaderLayout = QHBoxLayout(self.processHeaderWidget)
        self.processHeaderLayout.setContentsMargins(0, 0, 0, 0)

        self.processLabel = QLabel('Available processes:')
        self.githubLabel = QLabel('<a href="https://github.com/darktohka/p3dephaser">GitHub</a>')
        self.githubLabel.setOpenExternalLinks(True)

        self.refreshButton = QPushButton('Refresh')
        self.refreshButton.clicked.connect(self.refreshProcesses)
        self.refreshButton.setFixedSize(100, 23)

        self.multifileWidget = QWidget()
        self.multifileLayout = QHBoxLayout(self.multifileWidget)
        self.multifileLayout.setContentsMargins(0, 0, 0, 0)
        self.multifileLabel = QLabel('Requested multifile names:')
        self.multifileBox = QLineEdit(self)
        self.multifileBox.returnPressed.connect(self.beginScan)

        self.multifileLayout.addWidget(self.multifileLabel)
        self.multifileLayout.addWidget(self.multifileBox)

        self.scanButton = QPushButton('Scan')
        self.scanButton.clicked.connect(self.beginScan)

        self.processListBox = QListWidget()

        self.processHeaderLayout.addWidget(self.processLabel)
        self.processHeaderLayout.addStretch(1)
        self.processHeaderLayout.addWidget(self.githubLabel)
        self.processHeaderLayout.addWidget(self.refreshButton)

        self.resultTable = QTableWidget()
        self.resultTable.setColumnCount(3)
        self.resultTable.horizontalHeader().setStretchLastSection(True)
        self.resultTable.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        for i, header in enumerate(('Process', 'Multifile', 'Password')):
            self.resultTable.setHorizontalHeaderItem(i, QTableWidgetItem(header))

        self.baseLayout = QVBoxLayout(self)
        self.baseLayout.setContentsMargins(15, 15, 15, 15)
        self.baseLayout.addWidget(self.processHeaderWidget)
        self.baseLayout.addWidget(self.processListBox)
        self.baseLayout.addWidget(self.multifileWidget)
        self.baseLayout.addWidget(self.scanButton)
        self.baseLayout.addWidget(self.resultTable)

        self.refreshProcesses()

        self.threadPool = QThreadPool()
        self.worker = None
        self.processName = None
        self.nextClick = 0
        self.stopEvent = threading.Event()

    def setBackgroundColor(self, color):
        self.setAutoFillBackground(True)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), color)
        self.setPalette(palette)

    def getProcesses(self):
        processes = []

        for proc in psutil.process_iter():
            processes.append(proc.as_dict(attrs=['pid', 'name']))

        processes.sort(key=lambda process: (process['name'].lower(), process['pid']))
        return processes

    def refreshProcesses(self):
        self.processListBox.clear()
        processes = self.getProcesses()

        for process in processes:
            name = process['name']
            pid = process['pid']
            self.processListBox.addItem(f'{name} (PID {pid})')

    def beginScan(self):
        if self.worker:
            self.stopEvent.set()
            self.scanButton.setEnabled(False)
            return

        items = self.processListBox.selectedItems()

        if not items:
            QMessageBox.warning(self, TITLE, 'Please choose a process from the list!')
            return

        process = items[0].text()[:-1].split(' ')
        self.processName = ' '.join(process[:-2])
        pid = int(process[-1])
        multifiles = self.multifileBox.text().split()

        if not multifiles:
            QMessageBox.warning(self, TITLE, 'Please choose some multifiles to target!')
            return

        multifile_names = '\n'.join([f'- {multifile}' for multifile in multifiles])
        question = f'Do you really want to scan {self.processName} for the following multifiles?\n\n{multifile_names}'

        if QMessageBox.question(self, TITLE, question, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) != QMessageBox.Yes:
            return

        self.count = 0

        self.setWindowTitle(f'{TITLE} - Scanning...')
        self.scanButton.setText('Stop')

        self.worker = ScanWorker(self, pid, multifiles)
        self.worker.signals.finished.connect(self.scanOver)
        self.worker.signals.error.connect(self.errorOccurred)
        self.worker.signals.progress.connect(self.reportProgress)

        self.threadPool.start(self.worker)

    def scanOver(self):
        self.worker = None
        self.stopEvent.clear()

        self.scanButton.setText('Scan')
        self.scanButton.setEnabled(True)
        self.setWindowTitle(TITLE)
        QMessageBox.information(self, TITLE, f'Scan complete!\n\n{self.count} password{"s have" if self.count != 1 else " has"} been found.')

    def errorOccurred(self, error):
        exc, value, message = error
        QMessageBox.critical(self, TITLE, f'An error has occurred while trying to scan this process!\n\n{exc} {value}\n\n{message}')

    def reportProgress(self, multifile, password):
        self.count += 1
        index = self.resultTable.rowCount()

        self.resultTable.insertRow(index)

        for i, value in enumerate((self.processName, multifile, password)):
            self.resultTable.setItem(index, i, QTableWidgetItem(value))
Exemple #44
0
class DownloadDialog(QtWidgets.QDialog):
    def __init__(self, appctxt, BbRouter, download_dir,
                 modules: List[Tuple[str,
                                     str]], last_dialog: QtWidgets.QDialog):
        """Download Dialog for selecting files to download/ignore

        Args:
            appctxt (ApplicationContext): fbs application context
            BbRouter (str): authentication token
            download_dir (str): download directory
            modules (List[Tuple[str, str]]): list of course name and course id tuples
            last_dialog (QtWidgets.QDialog): last dialog to return on back button press
        """
        super(DownloadDialog, self).__init__()
        uic.loadUi(appctxt.get_resource("layouts/download.ui"), self)

        self.logger = Logger(appctxt)

        self.appctxt = appctxt
        self.BbRouter = BbRouter
        self.download_dir = download_dir
        self.modules = modules
        self.last_dialog = last_dialog
        dirLabel = self.findChild(QtWidgets.QLabel, "downloadDirLabel")
        dirLabel.setText("Downloading to: {}".format(download_dir))

        # load icons
        backIcon = QtGui.QIcon(appctxt.get_resource("images/back.png"))
        self.folderIcon = QtGui.QIcon(
            appctxt.get_resource("images/folder.png"))
        self.videoIcon = QtGui.QIcon(appctxt.get_resource("images/video.png"))
        self.fileIcon = QtGui.QIcon(appctxt.get_resource("images/file.png"))

        # load buttons
        self.backButton = self.findChild(QtWidgets.QToolButton, "backButton")
        self.backButton.setIcon(backIcon)
        self.ignoreButton = self.findChild(QtWidgets.QPushButton,
                                           "ignoreButton")
        self.downloadButton = self.findChild(QtWidgets.QPushButton,
                                             "downloadButton")
        self.selectAllButton = self.findChild(QtWidgets.QPushButton,
                                              "selectAllButton")
        self.deselectAllButton = self.findChild(QtWidgets.QPushButton,
                                                "deselectAllButton")
        self.reloadButton = self.findChild(QtWidgets.QPushButton,
                                           "reloadButton")
        self.selectFilesButton = self.findChild(QtWidgets.QPushButton,
                                                "selectFilesButton")
        self.selectVideosButton = self.findChild(QtWidgets.QPushButton,
                                                 "selectVideosButton")

        self.backButton.clicked.connect(self.handle_back)
        self.selectAllButton.clicked.connect(self.handle_select_all)
        self.deselectAllButton.clicked.connect(self.handle_unselect_all)
        self.ignoreButton.clicked.connect(self.handle_ignore)
        self.downloadButton.clicked.connect(self.handle_download)
        self.reloadButton.clicked.connect(self.handle_reload)
        self.selectFilesButton.clicked.connect(self.handle_select_files)
        self.selectVideosButton.clicked.connect(self.handle_select_videos)

        self.progressBar = self.findChild(QtWidgets.QProgressBar,
                                          "progressBar")
        self.progressBar.setValue(0)

        self.downloadProgressText = self.findChild(QtWidgets.QLabel,
                                                   "downloadProgressText")
        self.downloadProgressText.setText(
            "Click download to start downloading files")

        # get download dir from NTU Learn and load tree
        self.threadPool = QThreadPool()
        self.tree = self.findChild(QtWidgets.QTreeWidget, "treeWidget")

        # NOTE do not show tree even though we have data as we want the user to
        # act on fresh download data
        self.storage = Storage(download_dir)
        self.data = self.storage.download_dir

        # add loading text
        node = QtWidgets.QTreeWidgetItem(self.tree)
        node.setText(0, "Click Reload to pull data from NTU Learn")

        self.show()

    def closeEvent(self, event):
        self.storage.save_download_dir(self.data)

    def handle_back(self):
        # self.main = ChooseDirDialog(self.appctxt, self.BbRouter)
        self.main = self.last_dialog(self.appctxt, self.BbRouter)
        self.main.show()
        self.close()

    def handle_select_files(self):
        self.__handle_select_type(obj_type="file")

    def handle_select_videos(self):
        self.__handle_select_type(obj_type="recorded_lecture")

    def handle_reload(self):
        """
        1. disable reload button until done fetching data
        2. clear tree and add Loading text node
        3. in a separate thread make ntu_learn_downloader API call
        4. when done update UI
        """
        self.reloadButton.setEnabled(False)
        self.__clear_tree()
        node = QtWidgets.QTreeWidgetItem(self.tree)
        node.setText(0, "Loading...")

        def get_data(progress_callback) -> List[Dict]:
            """Get download dir from NTU Learn, WARNING slow, should not be run in main thread
            Returns list of dicts
            """
            result = [
                get_download_dir(self.BbRouter, name, course_id)
                for name, course_id in self.modules
            ]
            return result

        def save_data(result):
            self.storage.merge_download_dir(result)
            self.data = result
            self.data_to_tree()

        def finished():
            self.reloadButton.setEnabled(True)

        worker = Worker(get_data)
        worker.signals.result.connect(save_data)
        worker.signals.finished.connect(finished)

        self.threadPool.start(worker)

    def handle_select_all(self):
        def traverse(node):
            node.setCheckState(0, Qt.Checked)
            for index in range(node.childCount()):
                traverse(node.child(index))

        root = self.tree.invisibleRootItem()
        traverse(root)

    def handle_unselect_all(self):
        def traverse(node):
            node.setCheckState(0, Qt.Unchecked)
            for index in range(node.childCount()):
                traverse(node.child(index))

        root = self.tree.invisibleRootItem()
        traverse(root)

    def handle_ignore(self):
        """Dummy files are in the format: .{name} 
        Do not have to get the actual filename
        """
        alert = QtWidgets.QMessageBox()
        alert.setWindowTitle("Ignore selected files")
        alert.setIcon(QtWidgets.QMessageBox.Warning)
        alert.setText(
            "You are about to ignore some files. This will generate hidden files in your download directory"
        )
        alert.setDetailedText(
            "This will generate hidden files in the download directory so that ignored "
            "files will not appear the menu in the future.\n"
            "To undo, you need to enable show hidden files in your file "
            "explorer and remove the files you want to download. E.g. if you want to download Tut_4, look for .Tut_4 and remove it"
        )
        alert.setStandardButtons(QtWidgets.QMessageBox.Ok
                                 | QtWidgets.QMessageBox.Cancel)

        retval = alert.exec_()
        if retval == QtWidgets.QMessageBox.Ok:
            path_and_nodes = self.get_paths_and_selected_nodes()
            for path, node in path_and_nodes:
                node_data = node.data(0, Qt.UserRole)
                create_dummy_file(path, sanitise_filename(node_data["name"]))
            self.downloadProgressText.setText(
                "Ignored {} files and recorded lectures".format(
                    len(path_and_nodes)))
        if retval == QtWidgets.QMessageBox.Cancel:
            pass

    def handle_error(self, full_file_name: str, trace: str):
        """Create a MessageBox with a trace dump and log error to server
        """
        try:
            self.logger.log_error(trace)
        except Exception:
            pass

        alert = QtWidgets.QMessageBox()
        alert.setWindowTitle("Failed to get download link")
        alert.setText(
            "Failed to get download link for: {}. Please try again later. ".
            format(full_file_name) +
            "If the problem persists, please send the trace log below to us.")
        nonBoldFont = QtGui.QFont()
        nonBoldFont.setBold(False)
        alert.setDetailedText(trace)
        alert.setFont(nonBoldFont)
        alert.exec_()

    def handle_download(self):
        """
        1. Get list of files to download
        2. Map predownload links to download links
        3. Download files async in background
        4. update tree with downloaded items removed
        """
        self.setDownloadIgnoreButtonsEnabled(False)
        self.downloadProgressText.setText("Getting items to download...")
        paths_and_nodes = self.get_paths_and_selected_nodes()
        numFiles = len(paths_and_nodes)
        self.progressBar.setRange(0, numFiles)

        def download_from_nodes(progress_callback):
            """Return tuple (files downloaded, files skipped, download_links)
            """

            numDownloaded, numSkipped = 0, 0
            data_deltas = []

            for idx, (path, node) in enumerate(paths_and_nodes):
                node_data = node.data(0, Qt.UserRole)
                node_type = node_data["type"]

                save_flag = False
                # load the download link and file name from API if needed
                if node_data.get("download_link") is None:
                    save_flag = True
                    try:
                        if node_type == "file":
                            download_link = get_file_download_link(
                                self.BbRouter, node_data["predownload_link"])
                            filename = get_filename_from_url(download_link)
                        elif node_type == "recorded_lecture":
                            download_link = get_recorded_lecture_download_link(
                                self.BbRouter, node_data["predownload_link"])
                            filename = node_data["name"] + ".mp4"
                    except Exception:
                        trace = traceback.format_exc()
                        progress_callback.emit((idx + 1, node_data["name"],
                                                False, None, None, trace))
                        data_deltas.append(None)
                        continue
                else:
                    download_link = node_data.get("download_link")
                    filename = node_data.get("filename")

                full_file_path = os.path.join(path,
                                              sanitise_filename(filename))
                if os.path.exists(full_file_path):
                    numSkipped += 1
                    progress_callback.emit(
                        (idx + 1, filename, False, None, None, None))
                else:
                    try:
                        download(
                            self.BbRouter,
                            download_link,
                            full_file_path,
                            lambda bytes_downloaded, total_content_length:
                            progress_callback.emit((
                                idx + 1,
                                filename,
                                True,
                                bytes_downloaded,
                                total_content_length,
                                None,
                            )),
                        )
                    except Exception:
                        numSkipped += 1
                        trace = traceback.format_exc()
                        progress_callback.emit(
                            (idx + 1, filename, False, None, None, trace))

                numDownloaded += 1
                data_deltas.append((download_link,
                                    filename) if save_flag else None)

            return (numDownloaded, numSkipped, data_deltas)

        def progress_fn(data):
            """
            Progress text format:
            [overall_progress] [prefix] [filename] [current_file_progress]
            """
            numDownloaded, filename, was_last_downloaded, bytes_downloaded, total_content_length, stack_trace = (
                data)

            overall_progress = "({}/{})".format(numDownloaded, numFiles)
            prefix = "Downloading" if was_last_downloaded else "Skipping"
            current_file_progress = ""
            if was_last_downloaded:
                current_file_progress = ("({}/{})".format(
                    convert_size(bytes_downloaded),
                    convert_size(total_content_length),
                ) if total_content_length else "({})".format(
                    convert_size(bytes_downloaded)))

            text = "{} {} {} {}".format(overall_progress, prefix, filename,
                                        current_file_progress)
            self.downloadProgressText.setText(text)
            self.progressBar.setValue(numDownloaded)

            if stack_trace:
                self.handle_error(filename, stack_trace)

        def display_result_and_update_node_data(result):
            self.setDownloadIgnoreButtonsEnabled(True)
            numDownloaded, numSkipped, data_deltas = result
            self.downloadProgressText.setText(
                "Completed. Downloaded {} files, skipped {} files".format(
                    numDownloaded, numSkipped))

            for delta, (_path, node) in zip(data_deltas, paths_and_nodes):
                if delta is None:
                    continue
                download_link, filename = delta
                node_data = node.data(0, Qt.UserRole)
                node_data["download_link"] = download_link
                node_data["filename"] = filename
                node.setData(0, Qt.UserRole, node_data)

            try:
                self.logger.log_successful_download(numDownloaded)
            except Exception:
                pass

        worker = Worker(download_from_nodes)
        worker.signals.result.connect(display_result_and_update_node_data)
        worker.signals.finished.connect(self.reload_tree)
        worker.signals.progress.connect(progress_fn)

        self.threadPool.start(worker)

    def reload_tree(self):
        """update self.data based on new tree node data
        """
        self.tree_to_data()
        self.__clear_tree()
        self.data_to_tree()

    def tree_to_data(self):
        """traverse tree to convert it to data and update self.data
        """
        def traverse(node):
            node_data = node.data(0, Qt.UserRole)
            node_type = node_data["type"]

            if node_type == "folder":
                node_data["children"] = [
                    traverse(node.child(idx))
                    for idx in range(node.childCount())
                ]
            return node_data

        root = self.tree.invisibleRootItem()
        self.data = [
            traverse(root.child(idx)) for idx in range(root.childCount())
        ]

    def data_to_tree(self):
        """traverse self.data and generate tree list widget. Files/videos that have already downloaded
        will not be displayed
        Raises:
            Exception: thrown on unknown data type
        """
        if self.data is None:
            print(
                "Warning, there is not loaded data, was get_data() not called?"
            )
            return
        self.__clear_tree()

        def traverse(data, parent, path):
            """recursively traverse NTU Learn data and render all file/video nodes, if the 
            file/video already exists, set the node as hidden
            """
            node = QtWidgets.QTreeWidgetItem(parent)
            # save relevant data fields into node.data
            node_data = {"name": data["name"], "type": data["type"]}

            data_type = data["type"]
            if data_type == "folder":
                node.setIcon(0, self.folderIcon)
                node.setFlags(node.flags() | Qt.ItemIsTristate
                              | Qt.ItemIsUserCheckable)
                next_path = os.path.join(path, sanitise_filename(data["name"]),
                                         "")
                for child in data["children"]:
                    traverse(child, node, next_path)
            elif data_type == "file" or data_type == "recorded_lecture":
                # add file/video attributes
                node_data["predownload_link"] = data["predownload_link"]
                node_data["download_link"] = data.get("download_link")
                node_data["filename"] = data.get("filename")

                # ignore file if dummy file is present
                is_dummy_file_present = dummy_file_exists(
                    path, sanitise_filename(node_data["name"]))
                is_file_present = node_data["filename"] and os.path.exists(
                    os.path.join(path, sanitise_filename(
                        node_data["filename"])))

                if is_dummy_file_present or is_file_present:
                    node.setHidden(True)

                node.setIcon(
                    0,
                    self.fileIcon if data_type == "file" else self.videoIcon)
                node.setFlags(node.flags() | Qt.ItemIsUserCheckable)
            else:
                raise Exception("unknown type", data_type)
            node.setText(0, data["name"])
            node.setCheckState(0, Qt.Unchecked)
            node.setData(0, Qt.UserRole, node_data)

        # iterate data (list)
        for item in self.data:
            traverse(item, self.tree, self.download_dir)

    def get_paths_and_selected_nodes(
            self,
            files=True,
            videos=False) -> List[Tuple[str, QtWidgets.QTreeWidgetItem]]:
        """returns lists of QTreeWidgetItem (nodes) that correspond to files/videos to download/ignore

        Args:
            files (bool, optional): whether to download files. Defaults to True.
            videos (bool, optional): whether to download videos. Defaults to False.

        Returns:
           List[Tuple[str, QtWidgets.QTreeWidgetItem]]: list of path, tree nodes tuples
        
        Note:
            Not possible to project down to filename, download link as loading of the downloading 
            link is very slow (3s) for lecture videos
        """

        result = []

        def traverse(node, path):
            if node.checkState(0) == Qt.Unchecked or node.isHidden():
                return

            node_data = node.data(0, Qt.UserRole)
            node_type = node_data["type"]
            if node_type == "file" or node_type == "recorded_lecture":
                result.append((path, node))
            else:
                next_path = os.path.join(path,
                                         sanitise_filename(node_data["name"]))
                for index in range(node.childCount()):
                    traverse(node.child(index), next_path)

        root = self.tree.invisibleRootItem()
        for idx in range(root.childCount()):
            traverse(root.child(idx), self.download_dir)

        return result

    def setDownloadIgnoreButtonsEnabled(self, flag: bool):
        self.downloadButton.setEnabled(flag)
        self.ignoreButton.setEnabled(flag)

    def __clear_tree(self):
        self.tree.clear()

    def __handle_select_type(self, obj_type: str):
        assert obj_type in [
            "file",
            "recorded_lecture",
        ], "unexpected obj_type: {}".format(obj_type)

        def is_same_type(node, obj_type: str) -> bool:
            node_data = node.data(0, Qt.UserRole)
            node_type = isinstance(node_data, dict) and node_data["type"]
            node_name = isinstance(node_data, dict) and node_data["name"]
            if obj_type == "file":
                return (node_type == obj_type and isinstance(node_name, str)
                        and not node_name.endswith(".mp4"))
            else:
                return node_type == "recorded_lecture" or (isinstance(
                    node_name, str) and node_name.endswith(".mp4"))

        def traverse(node):
            if is_same_type(node, obj_type):
                node.setCheckState(0, Qt.Checked)
            else:
                for index in range(node.childCount()):
                    traverse(node.child(index))

        root = self.tree.invisibleRootItem()
        traverse(root)
Exemple #45
0
class RelialokMainWindow(object):
    def __init__(self, MainWindow, *args, **kwargs):
        '''
        Main front-end GUI class. Defines backend functions for hardware interface and front-end widgets for control and
        monitoring of interlock.

        :param MainWindow:
        :param args: MainWindow (QtWidgets.QMainWindow())
        :param kwargs: None
        '''

        # Class variables and flags
        self.connection_open = False
        self.com_ports = [
            comport.device for comport in serial.tools.list_ports.comports()
        ]
        self.serial = None
        self.setup_ui(MainWindow)

    def setup_ui(self, MainWindow):
        '''
        Definition of GUI widgets, positioning, and framing. Also connects functions to widget hooks.
        '''

        # Gui definition
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(933, 725)
        MainWindow.setMinimumSize(QtCore.QSize(933, 725))
        MainWindow.setMaximumSize(QtCore.QSize(934, 726))
        MainWindow.setAutoFillBackground(True)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        # Define GUI button positions
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(670, 650, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(750, 650, 75, 23))
        self.pushButton_2.setAutoFillBackground(True)
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_7 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_7.setGeometry(QtCore.QRect(830, 650, 75, 23))
        self.pushButton_7.setObjectName("pushButton_7")

        # Define text box
        self.textBox = QtWidgets.QTextEdit(self.centralwidget)
        self.textBox.setGeometry(QtCore.QRect(20, 240, 881, 381))
        self.textBox.setObjectName("textBox")

        # Define cursor in text box
        self.cursor = QTextCursor(self.textBox.document())

        # Define GUI structure & grid layout
        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect(20, 160, 321, 16))
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")

        self.line_2 = QtWidgets.QFrame(self.centralwidget)
        self.line_2.setGeometry(QtCore.QRect(420, 160, 321, 20))
        self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setGeometry(QtCore.QRect(360, 160, 47, 16))

        self.gridLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget_2.setGeometry(QtCore.QRect(759, 30, 141, 201))
        self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setObjectName("gridLayout_2")

        self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 190, 721, 41))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(
            self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(20, 29, 721, 111))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.gridLayout_3.setSpacing(20)

        self.widget = QtWidgets.QWidget(self.gridLayoutWidget_2)
        self.widget.setObjectName("widget")

        self.gridLayout_2.addWidget(self.widget, 0, 0, 1, 1)
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(20, 650, 69, 22))
        self.comboBox.setObjectName("com_ports")
        self.comboBox.addItems(self.com_ports)

        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)

        # Place & configure buttons

        self.pushButton_4 = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.pushButton_4.sizePolicy().hasHeightForWidth())
        self.pushButton_4.setSizePolicy(sizePolicy)
        self.pushButton_4.setObjectName("pushButton_4")
        self.gridLayout_2.addWidget(self.pushButton_4, 1, 0, 1, 1)

        self.pushButton_5 = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.pushButton_5.sizePolicy().hasHeightForWidth())
        self.pushButton_5.setSizePolicy(sizePolicy)
        self.pushButton_5.setObjectName("pushButton_5")
        self.gridLayout_2.addWidget(self.pushButton_5, 3, 0, 1, 1)

        self.pushButton_6 = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.pushButton_6.sizePolicy().hasHeightForWidth())
        self.pushButton_6.setSizePolicy(sizePolicy)
        self.pushButton_6.setObjectName("pushButton_6")
        self.gridLayout_2.addWidget(self.pushButton_6, 2, 0, 1, 1)

        # Define readout LEDs and place in GUI structure

        # Power ON light
        self.led_25 = LedIndicatorWidget.LedIndicator(color='blue')
        self.gridLayout_2.addWidget(self.led_25, 0, 0, 1, 1)
        self.led_25.setGeometry(QtCore.QRect(40, 0, 61, 31))
        self.led_25.setObjectName("led_25")
        self.led_25.setChecked(False)

        # Fault 1
        self.led_f1 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f1.setObjectName("led_fault_1")
        self.horizontalLayout.addWidget(self.led_f1)
        self.led_f1.setChecked(False)

        # Fault 2
        self.led_f2 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f2.setObjectName("led_fault_2")
        self.horizontalLayout.addWidget(self.led_f2)
        self.led_f2.setChecked(False)

        # Fault 3
        self.led_f3 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f3.setObjectName("led_fault_3")
        self.horizontalLayout.addWidget(self.led_f3)
        self.led_f3.setChecked(False)

        # Fault 4
        self.led_f4 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f4.setObjectName("led_fault_4")
        self.horizontalLayout.addWidget(self.led_f4)
        self.led_f4.setChecked(False)

        # Fault 5
        self.led_f5 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f5.setObjectName("led_fault_5")
        self.horizontalLayout.addWidget(self.led_f5)
        self.led_f5.setChecked(False)

        # Fault 6
        self.led_f6 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f6.setObjectName("led_fault_6")
        self.horizontalLayout.addWidget(self.led_f6)
        self.led_f6.setChecked(False)

        # Fault 7
        self.led_f7 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f7.setObjectName("led_fault_7")
        self.horizontalLayout.addWidget(self.led_f7)
        self.led_f7.setChecked(False)

        # Fault 8
        self.led_f8 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_f8.setObjectName("led_fault_8")
        self.horizontalLayout.addWidget(self.led_f8)
        self.led_f8.setChecked(False)

        # ON-1
        self.led_on_1 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_1.setObjectName("led_on_1")
        self.gridLayout_3.addWidget(self.led_on_1, 1, 0, 1, 1)
        self.led_on_1.setChecked(False)

        # OFF-1
        self.led_off_1 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_1.setObjectName("led_off_2")
        self.gridLayout_3.addWidget(self.led_off_1, 2, 0, 1, 1)
        self.led_off_1.setChecked(False)

        # ON-2
        self.led_on_2 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_2.setObjectName("led_on_2")
        self.gridLayout_3.addWidget(self.led_on_2, 1, 1, 1, 1)
        self.led_on_2.setChecked(False)

        # OFF-2
        self.led_off_2 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_2.setObjectName("led_off_2")
        self.gridLayout_3.addWidget(self.led_off_2, 2, 1, 1, 1)
        self.led_off_2.setChecked(False)

        # ON-3
        self.led_on_3 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_3.setObjectName("led_on_3")
        self.gridLayout_3.addWidget(self.led_on_3, 1, 2, 1, 1)
        self.led_on_3.setChecked(False)

        # OFF-3
        self.led_off_3 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_3.setObjectName("led_off_3")
        self.gridLayout_3.addWidget(self.led_off_3, 2, 2, 1, 1)
        self.led_off_3.setChecked(False)

        # ON-4
        self.led_on_4 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_4.setObjectName("led_on_4")
        self.gridLayout_3.addWidget(self.led_on_4, 1, 3, 1, 1)
        self.led_on_4.setChecked(False)

        # OFF-4
        self.led_off_4 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_4.setObjectName("led_off_4")
        self.gridLayout_3.addWidget(self.led_off_4, 2, 3, 1, 1)
        self.led_off_4.setChecked(False)

        # ON-5
        self.led_on_5 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_5.setObjectName("led_on_5")
        self.gridLayout_3.addWidget(self.led_on_5, 1, 4, 1, 1)
        self.led_on_5.setChecked(False)

        # OFF-5
        self.led_off_5 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_5.setObjectName("led_off_5")
        self.gridLayout_3.addWidget(self.led_off_5, 2, 4, 1, 1)
        self.led_off_5.setChecked(False)

        # ON-6
        self.led_on_6 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_6.setObjectName("led_on_6")
        self.gridLayout_3.addWidget(self.led_on_6, 1, 5, 1, 1)
        self.led_on_6.setChecked(False)

        # OFF-6
        self.led_off_6 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_6.setObjectName("led_off_6")
        self.gridLayout_3.addWidget(self.led_off_6, 2, 5, 1, 1)
        self.led_off_6.setChecked(False)

        # ON-7
        self.led_on_7 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_7.setObjectName("led_on_7")
        self.gridLayout_3.addWidget(self.led_on_7, 1, 6, 1, 1)
        self.led_on_7.setChecked(False)

        # OFF-7
        self.led_off_7 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_7.setObjectName("led_off_7")
        self.gridLayout_3.addWidget(self.led_off_7, 2, 6, 1, 1)
        self.led_off_7.setChecked(False)

        # ON-8
        self.led_on_8 = LedIndicatorWidget.LedIndicator(color='green')
        self.led_on_8.setObjectName("led_on_8")
        self.gridLayout_3.addWidget(self.led_on_8, 1, 7, 1, 1)
        self.led_on_8.setChecked(False)

        # OFF-8
        self.led_off_8 = LedIndicatorWidget.LedIndicator(color='red')
        self.led_off_8.setObjectName("led_off_8")
        self.gridLayout_3.addWidget(self.led_off_8, 2, 7, 1, 1)
        self.led_off_8.setChecked(False)

        # Define labels & place
        self.label_6 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_6.setAlignment(QtCore.Qt.AlignCenter)
        self.label_6.setObjectName("label_6")
        self.gridLayout_3.addWidget(self.label_6, 0, 5, 1, 1)

        self.label = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1)

        self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName("label_2")
        self.gridLayout_3.addWidget(self.label_2, 0, 1, 1, 1)

        self.label_3 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_3.setAlignment(QtCore.Qt.AlignCenter)
        self.label_3.setObjectName("label_3")
        self.gridLayout_3.addWidget(self.label_3, 0, 2, 1, 1)

        self.label_4 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_4.setAlignment(QtCore.Qt.AlignCenter)
        self.label_4.setObjectName("label_4")
        self.gridLayout_3.addWidget(self.label_4, 0, 3, 1, 1)

        self.label_5 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_5.setAlignment(QtCore.Qt.AlignCenter)
        self.label_5.setObjectName("label_5")
        self.gridLayout_3.addWidget(self.label_5, 0, 4, 1, 1)

        self.label_7 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_7.setAlignment(QtCore.Qt.AlignCenter)
        self.label_7.setObjectName("label_7")
        self.gridLayout_3.addWidget(self.label_7, 0, 6, 1, 1)

        self.label_8 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_8.setAlignment(QtCore.Qt.AlignCenter)
        self.label_8.setObjectName("label_8")
        self.gridLayout_3.addWidget(self.label_8, 0, 7, 1, 1)

        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 933, 21))
        self.menubar.setObjectName("menubar")
        self.menuOctolok = QtWidgets.QMenu(self.menubar)
        self.menuOctolok.setObjectName("menuOctolok")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menuOctolok.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # Define function dispatcher to set state of of LED

        self.dispatcher = {
            'FAULT': [
                self.led_f1.setChecked, self.led_f2.setChecked,
                self.led_f3.setChecked, self.led_f4.setChecked,
                self.led_f5.setChecked, self.led_f6.setChecked,
                self.led_f7.setChecked, self.led_f8.setChecked
            ],
            'ON-OFF': [[self.led_on_1.setChecked, self.led_off_1.setChecked],
                       [self.led_on_2.setChecked, self.led_off_2.setChecked],
                       [self.led_on_3.setChecked, self.led_off_3.setChecked],
                       [self.led_on_4.setChecked, self.led_off_4.setChecked],
                       [self.led_on_5.setChecked, self.led_off_5.setChecked],
                       [self.led_on_6.setChecked, self.led_off_6.setChecked],
                       [self.led_on_7.setChecked, self.led_off_7.setChecked],
                       [self.led_on_8.setChecked, self.led_off_8.setChecked]]
        }

        # Button hooks
        self.pushButton.clicked.connect(self.connect)
        self.pushButton_2.clicked.connect(self.disconnect)
        self.pushButton_4.clicked.connect(self.get_status)
        self.pushButton_6.clicked.connect(lambda: self.decode('DISABLE '))
        self.pushButton_7.clicked.connect(self.close)

    def retranslateUi(self, MainWindow):
        '''
        Redefines label and button names for front-end usages.
        :param MainWindow: QtWidgets.QMainWindow()
        :return: None
        '''

        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Connect"))
        self.pushButton_2.setText(_translate("MainWindow", "Disconnect"))
        self.pushButton_4.setText(_translate("MainWindow", "Status"))
        self.pushButton_5.setText(_translate("MainWindow", "Reset"))
        self.pushButton_6.setText(_translate("MainWindow", "Disable"))
        self.pushButton_7.setText(_translate("MainWindow", "Close"))
        self.label_5.setText(_translate("MainWindow", "5"))
        self.label_6.setText(_translate("MainWindow", "6"))
        self.label.setText(_translate("MainWindow", "1"))
        self.label_3.setText(_translate("MainWindow", "3"))
        self.label_7.setText(_translate("MainWindow", "7"))
        self.label_2.setText(_translate("MainWindow", "2"))
        self.label_8.setText(_translate("MainWindow", "8"))
        self.label_4.setText(_translate("MainWindow", "4"))
        self.label_9.setText(_translate("MainWindow", "Fault"))
        self.menuOctolok.setTitle(_translate("MainWindow", "Octolok"))

        # Start thread
        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" %
              self.threadpool.maxThreadCount())

    def connect(self):
        '''
        Create instance of serial port handler, SerialPort(). Passes combo boxx selection containing current serial port.
        :return: None
        '''

        self.print_output(
            "Initializing serial connection on port: {port}".format(
                port=self.comboBox.currentText()))
        self.serial = SerialPort(self.comboBox.currentText())
        self.connection_open = True
        self.listen()

    def close(self):
        '''
        Ends MainWindow session.
        :return: None
        '''
        self.threadpool.waitForDone(2000)
        self.serial.disconnect()
        MainWindow.close()

    def disconnect(self):
        '''
        Waits for completion of current thread in threadpool and closes serial port connection. If current connection
        doesn't exist, function passes and does nothing.
        :return: None
        '''

        if self.connection_open:
            try:
                self.print_output(
                    "Disconnecting serial connection on port: {port}".format(
                        port=self.comboBox.currentText()))
                self.threadpool.waitForDone(2000)
                self.threadpool.clear()
                self.serial.disconnect()
                self.led_25.setChecked(False)
            except Exception as ex:
                pass
        else:
            self.print_output('Connection not active. Please connect.')

    def print_output(self, s):
        '''
        Wrapper function to print to front-end text box.
        :param s: string-type to send to text box.
        :return: None
        '''

        self.cursor.setPosition(0)
        self.textBox.setTextCursor(self.cursor)
        self.textBox.insertPlainText('[{ts}] {msg}\n'.format(ts=time.ctime(
            time.time())[11:-5],
                                                             msg=s))

    def decode(self, message):
        '''
        Parses and decodes incoming communication from hardware device.
        :param reply: string-type reply or interrupt message from hardware.
        :return: None
        '''

        self.print_output('Decoding response ...')
        try:
            type, reply = message.split(' ')
            reply = reply.strip()

            self.status = reply[::2]
            self.state = reply[1::2]
            self.status = [
                bool(int(self.status[i])) for i in range(len(self.status))
            ]
            self.state = [
                bool(int(self.state[i])) for i in range(len(self.state))
            ]

            if type == 'STATUS':
                for (on, off), i in zip(self.dispatcher['ON-OFF'],
                                        range(len(self.dispatcher['ON-OFF']))):
                    if not self.status[i]:
                        on(False)
                        off(False)
                    else:
                        on(self.state[i])
                        off(not self.state[i])
            elif type == 'DISABLE':
                for (on, off), i in zip(self.dispatcher['ON-OFF'],
                                        range(len(self.dispatcher['ON-OFF']))):
                    on(False)
                    off(False)

            elif type == 'FAULT':
                self.fault = [
                    bool(int(self.reply[i])) for i in range(len(self.reply))
                ]
                for fault, i in zip(self.dispatcher['FAULT'],
                                    range(len(self.dispatcher['FAULT']))):
                    fault(self.fault[i])
            else:
                pass
        except AttributeError as ex:
            pass

    def data_received(self, data):
        print('Data at COM port:')
        self.print_output(data)

    def listen(self):
        '''
        Spanwns polling thread to look for interrupt communication form hardware device at COM port. Function has
        secondary priority to serial port resource.
        :return: None
        '''

        if self.connection_open:
            try:
                self.led_25.setChecked(True)
                # Pass the function to execute
                worker = WorkerThreading.Worker(self.serial.listen)
                worker.signals.result.connect(self.decode)
                #        worker.signals.finished.connect(self.thread_complete)
                worker.signals.progress.connect(self.data_received)

                # Execute
                self.threadpool.start(worker, priority=3)
            except Exception as ex:
                self.print_output(
                    'Error listening on port: {0}. Check log for more details.'
                    .format(ex))
        else:
            self.print_output('Connection not active. Please connect.')
            return

    def get_status(self):
        '''
        Spawns thread for sending command to hardware. Sends STATUS? command to hardware ans then waits for reply. Reply
        is sent to decode fucntion. Has top priority to serial port resource.
        :param cmd:
        :return:
        '''

        if self.connection_open:
            try:
                # Pass the function to execute
                worker = WorkerThreading.Worker(self.serial.send,
                                                command='STATUS?')
                worker.signals.result.connect(self.decode)
                #        worker.signals.finished.connect(self.thread_complete)
                # Execute
                self.threadpool.start(worker, priority=4)
            except Exception as ex:
                self.print_output(
                    'Error reading on port: {0}. Check log for more details.'.
                    format(ex))
        else:
            self.print_output('Connection not active. Please connect.')
            return
Exemple #46
0
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.

from PyQt5.QtCore import QRunnable, pyqtSlot, QThreadPool
from functools import wraps
import traceback

threadpool = QThreadPool()


class Runner(QRunnable):
    def __init__(self, func, *args, **kwargs):
        QRunnable.__init__(self)
        self.func = func
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):
        try:
            setattr(self.args[0], 'separate_thread_running', True)
        except:
            pass
Exemple #47
0
class ImageViewerWidget(QWidget,Ui_Image_Viewer_Widget):
    def __init__(self,parent=None):
        super(ImageViewerWidget,self).__init__(parent)
        self.setupUi(self)
        self.viewer=ImageViewer()
        self.viewer.scene().itemAdded.connect(self._scene_item_added)
        self.center_layout.addWidget(self.viewer,0,0)

        # self._label_background=QLabel()
        # self._label_background.setFixedHeight(40)
        # image = GUIUtilities.get_image("label.png")
        # self._label_background.setPixmap(image.scaledToHeight(40))
        # self.center_layout.addWidget(self._label_background,0,0,QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)

        self._label=QLabel()
        self._label.setVisible(False)
        self._label.setMargin(5)
        self._label.setStyleSheet('''
            QLabel{
            font: 12pt;
            border-radius: 25px;
            margin: 10px;
            color: black; 
            background-color: #FFFFDC;
            }
        ''')
        shadow=QGraphicsDropShadowEffect(self)
        shadow.setBlurRadius(8)
        # shadow.setColor(QtGui.QColor(76,35,45).lighter())
        shadow.setColor(QtGui.QColor(94, 93, 90).lighter())
        shadow.setOffset(2)
        self._label.setGraphicsEffect(shadow)
        self.center_layout.addWidget(self._label,0,0,QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)

        self.actions_layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter)
        self.actions_layout.setContentsMargins(0,5,0,0)
        self._ds_dao =  DatasetDao()
        self._hub_dao = HubDao()
        self._labels_dao = LabelDao()
        self._annot_dao = AnnotaDao()
        self._thread_pool=QThreadPool()
        self._loading_dialog=QLoadingDialog()
        self._source = None
        self._image = None
        self.images_list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection )
        #self.images_list_widget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.images_list_widget.currentItemChanged.connect(self.image_list_sel_changed_slot)
        self.images_list_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.images_list_widget.customContextMenuRequested.connect(self.image_list_context_menu)

        self.treeview_models=ModelsTreeview()
        self.treeview_models.setColumnWidth(0,300)
        self.tree_view_models_layout.addWidget(self.treeview_models)
        self.treeview_models.action_click.connect(self.trv_models_action_click_slot)

        self.treeview_labels = LabelsTableView()
        self.treeview_labels.action_click.connect(self.trv_labels_action_click_slot)
        self.tree_view_labels_layout.addWidget(self.treeview_labels)
        self.treeview_labels.selectionModel().selectionChanged.connect(self.default_label_changed_slot)
        #window = GUIUtilities.findMainWindow()
        #window.keyPressed.connect(self.window_keyPressEvent)
        self.create_actions_bar()

    def image_list_context_menu(self, pos: QPoint):
        menu=QMenu()
        result=self._labels_dao.fetch_all(self.source.dataset)
        if len(result) > 0:
            labels_menu=menu.addMenu("labels")
            for vo in result:
                action=labels_menu.addAction(vo.name)
                action.setData(vo)
        action=menu.exec_(QCursor.pos())
        if action and isinstance(action.data(),LabelVO):
            label=action.data()
            self.change_image_labels(label)

    def change_image_labels(self, label: LabelVO):
        items = self.images_list_widget.selectedItems()
        selected_images = []
        for item in items:
            vo = item.tag
            selected_images.append(vo)

        @work_exception
        def do_work():
            self._ds_dao.tag_entries(selected_images, label)
            return 1,None

        @gui_exception
        def done_work(result):
            status, err = result
            if err:
                raise err

        worker = Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)


    def default_label_changed_slot(self, selection: QItemSelection):
        selected_rows =self.treeview_labels.selectionModel().selectedRows(2)
        if len(selected_rows) > 0:
            index: QModelIndex = selected_rows[0]
            current_label: LabelVO=self.treeview_labels.model().data(index)
            self.viewer.current_label = current_label

    def image_list_sel_changed_slot(self,curr: CustomListWidgetItem,prev: CustomListWidgetItem):
        if curr: self.source = curr.tag

    @property
    def image(self):
        return self._image

    @property
    def source(self)-> DatasetEntryVO:
        return self._source

    @source.setter
    def source(self, value):
        if not isinstance(value, DatasetEntryVO):
            raise Exception("Invalid source")
        self._source= value
        image_path = self._source.file_path
        self._image=Image.open(image_path)
        self.viewer.pixmap=QPixmap(image_path)
        self.load_image_annotations()
        self.load_image_label()

    @gui_exception
    def load_images(self):
        @work_exception
        def do_work():
            entries=self._ds_dao.fetch_entries(self.source.dataset)
            return entries,None

        @gui_exception
        def done_work(result):
            data,error=result
            selected_item = None
            for vo in data:
                item = CustomListWidgetItem(vo.file_path)
                item.setIcon(GUIUtilities.get_icon("image.png"))
                item.tag = vo
                if vo.file_path == self.source.file_path:
                    selected_item = item
                self.images_list_widget.addItem(item)
                self.images_list_widget.setCursor(QtCore.Qt.PointingHandCursor)
                self.images_list_widget.setCurrentItem(selected_item)

        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)

    @gui_exception
    def load_models(self):
        @work_exception
        def do_work():
            results = self._hub_dao.fetch_all()
            return results, None

        @gui_exception
        def done_work(result):
            result, error = result
            if result:
                for model in result:
                    self.treeview_models.add_node(model)
        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)

    @gui_exception
    def load_labels(self):
        @work_exception
        def do_work():
            results = self._labels_dao.fetch_all(self.source.dataset)
            return results, None

        @gui_exception
        def done_work(result):
            result, error = result
            if error is None:
                for entry in result:
                    self.treeview_labels.add_row(entry)
        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)

    @gui_exception
    def load_image_annotations(self):
        @work_exception
        def do_work():
            results=self._annot_dao.fetch_all(self.source.id)
            return results,None

        @gui_exception
        def done_work(result):
            result,error=result
            if error:
                raise error
            img_bbox: QRectF=self.viewer.pixmap.sceneBoundingRect()
            offset=QPointF(img_bbox.width()/2,img_bbox.height()/2)
            for entry in result:
                try:
                    vo : AnnotaVO = entry
                    points = map(float,vo.points.split(","))
                    points = list(more_itertools.chunked(points, 2))
                    if vo.kind == "box":
                        x = points[0][0] - offset.x()
                        y=  points[0][1] - offset.y()
                        w = math.fabs(points[0][0] - points[1][0])
                        h = math.fabs(points[0][1] - points[1][1])
                        roi : QRectF = QRectF(x,y,w,h)
                        rect=EditableBox(roi)
                        rect.label = vo.label
                        self.viewer.scene().addItem(rect)
                    elif vo.kind == "polygon":
                        polygon = EditablePolygon()
                        polygon.label = vo.label
                        self.viewer.scene().addItem(polygon)
                        for p in points:
                            polygon.addPoint(QPoint(p[0] - offset.x(), p[1] - offset.y()))
                except Exception as ex:
                    print(ex)

        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)

    @gui_exception
    def load_image_label(self):
        @work_exception
        def do_work():
            label=self._annot_dao.get_label(self.source.id)
            return label,None

        @gui_exception
        def done_work(result):
            label_name,error=result
            if error:
                raise error
            if label_name:
                self._label.setVisible(True)
                self._label.setText(label_name)
            else:
                self._label.setVisible(False)
                self._label.setText("")
        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)

    @gui_exception
    def add_repository(self):

        @work_exception
        def do_work(repo):
            hub_client=HubClientFactory.create(Framework.PyTorch)
            hub=hub_client.fetch_model(repo,force_reload=True)
            self._hub_dao.save(hub)
            return hub,None

        @gui_exception
        def done_work(result):
            self._loading_dialog.close()
            data,error=result
            if error is None:
                self.treeview_models.add_node(data)

        form=NewRepoForm()
        if form.exec_() == QDialog.Accepted:
            repository=form.result
            worker=Worker(do_work, repository)
            worker.signals.result.connect(done_work)
            self._thread_pool.start(worker)
            self._loading_dialog.exec_()

    def keyPressEvent(self, event: QtGui.QKeyEvent) -> None:
        row = self.images_list_widget.currentRow()
        last_index = self.images_list_widget.count() - 1
        if event.key() == QtCore.Qt.Key_A:
            self.save_annotations()
            if row > 0:
                self.images_list_widget.setCurrentRow(row-1)
            else:
                self.images_list_widget.setCurrentRow(last_index)
        if event.key() == QtCore.Qt.Key_D:
            self.save_annotations()
            if row < last_index:
                self.images_list_widget.setCurrentRow(row+1)
            else:
                self.images_list_widget.setCurrentRow(0)
        if event.key() == QtCore.Qt.Key_W:
            self.viewer.selection_mode=SELECTION_MODE.POLYGON
        if event.key() == QtCore.Qt.Key_S:
            self.viewer.selection_mode=SELECTION_MODE.BOX
        super(ImageViewerWidget,self).keyPressEvent(event)

    @gui_exception
    def trv_models_action_click_slot(self, action:  QAction):
        if action.text() == self.treeview_models.CTX_MENU_NEW_DATASET_ACTION:
            self.add_repository()
        elif action.text() == self.treeview_models.CTX_MENU_AUTO_LABEL_ACTION:
            current_node = action.data()  # model name
            parent_node = current_node.parent  # repo
            repo, model = parent_node.get_data(0),current_node.get_data(0)
            self.autolabel(repo, model)

    @gui_exception
    def trv_labels_action_click_slot(self,action: QAction):
        model  = self.treeview_labels.model()
        if action.text() == self.treeview_labels.CTX_MENU_ADD_LABEL:
            form=NewLabelForm()
            if form.exec_() == QDialog.Accepted:
                label_vo: LabelVO=form.result
                label_vo.dataset=self.source.dataset
                label_vo = self._labels_dao.save(label_vo)
                self.treeview_labels.add_row(label_vo)
        elif action.text() == self.treeview_labels.CTX_MENU_DELETE_LABEL:
            index : QModelIndex = action.data()
            if index:
                label_vo=model.index(index.row(),2).data()
                self._labels_dao.delete(label_vo.id)
                self.viewer.remove_annotations_by_label(label_vo.name)
                model.removeRow(index.row())

    def autolabel(self, repo, model_name):
        def do_work():
            try:
                print(repo, model_name)
                from PIL import Image
                from torchvision import transforms
                import torch
                model=torch.hub.load(repo,model_name,pretrained=True)
                model.eval()
                input_image=Image.open(self.source.file_path)
                preprocess=transforms.Compose([
                    transforms.Resize(480),
                    transforms.ToTensor(),
                    transforms.Normalize(mean=[0.485,0.456,0.406],std=[0.229,0.224,0.225]),
                ])
                input_tensor=preprocess(input_image)
                input_batch=input_tensor.unsqueeze(0)  # create a mini-batch as expected by the model
                # move the param and model to GPU for speed if available
                if torch.cuda.is_available():
                    input_batch=input_batch.to('cuda')
                    model.to('cuda')
                with torch.no_grad():
                    output=model(input_batch)['out'][0]
                output_predictions=output.argmax(0)
                # create a color pallette, selecting a color for each class
                palette=torch.tensor([2 ** 25-1,2 ** 15-1,2 ** 21-1])
                colors=torch.as_tensor([i for i in range(21)])[:,None]*palette
                colors=(colors%255).numpy().astype("uint8")
                # plot the semantic segmentation predictions of 21 classes in each color
                predictions_array: np.ndarray=output_predictions.byte().cpu().numpy()
                predictions_image=Image.fromarray(predictions_array).resize(input_image.size)
                predictions_image.putpalette(colors)
                labels_mask=np.asarray(predictions_image)
                classes=list(filter(lambda x: x != 0,np.unique(labels_mask).tolist()))
                classes_map={c: [] for c in classes}
                for c in classes:
                    class_mask=np.zeros(labels_mask.shape,dtype=np.uint8)
                    class_mask[np.where(labels_mask == c)]=255
                    contour_list=cv2.findContours(class_mask.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
                    contour_list=imutils.grab_contours(contour_list)
                    for contour in contour_list:
                        points=np.vstack(contour).squeeze().tolist()
                        classes_map[c].append(points)
                return classes_map,None
            except Exception as ex:
                return None,ex

        def done_work(result):
            self._loading_dialog.close()
            classes_map,err=result
            if err:
                return
            for class_idx,contours in classes_map.items():
                for c in contours:
                    points=[]
                    for i in range(0,len(c),10):
                        points.append(c[i])
                    polygon=EditablePolygon()
                    self.viewer._scene.addItem(polygon)
                    bbox: QRectF=self.viewer.pixmap.boundingRect()
                    offset=QPointF(bbox.width()/2,bbox.height()/2)
                    for point in points:
                        polygon.addPoint(QPoint(point[0] - offset.x(),point[1] - offset.y()))

        worker=Worker(do_work)
        worker.signals.result.connect(done_work)
        self._thread_pool.start(worker)
        self._loading_dialog.exec_()

    def create_actions_bar(self):
        icon_size = QSize(28,28)

        self.btn_enable_polygon_selection=ImageButton(icon=GUIUtilities.get_icon("polygon.png"),size=icon_size)
        self.btn_enable_rectangle_selection=ImageButton(icon=GUIUtilities.get_icon("square.png"),size=icon_size)
        self.btn_enable_free_selection=ImageButton(icon=GUIUtilities.get_icon("highlighter.png"),size=icon_size)
        self.btn_enable_none_selection=ImageButton(icon=GUIUtilities.get_icon("cursor.png"),size=icon_size)
        self.btn_save_annotations = ImageButton(icon=GUIUtilities.get_icon("save-icon.png"),size=icon_size)
        self.btn_clear_annotations=ImageButton(icon=GUIUtilities.get_icon("clean.png"),size=icon_size)

        self.actions_layout.addWidget(self.btn_enable_rectangle_selection)
        self.actions_layout.addWidget(self.btn_enable_polygon_selection)
        self.actions_layout.addWidget(self.btn_enable_free_selection)
        self.actions_layout.addWidget(self.btn_enable_none_selection)
        self.actions_layout.addWidget(self.btn_clear_annotations)
        self.actions_layout.addWidget(self.btn_save_annotations)

        self.btn_save_annotations.clicked.connect(self.btn_save_annotations_clicked_slot)
        self.btn_enable_polygon_selection.clicked.connect(self.btn_enable_polygon_selection_clicked_slot)
        self.btn_enable_rectangle_selection.clicked.connect(self.btn_enable_rectangle_selection_clicked_slot)
        self.btn_enable_free_selection.clicked.connect(self.btn_enable_free_selection_clicked_slot)
        self.btn_enable_none_selection.clicked.connect(self.btn_enable_none_selection_clicked_slot)
        self.btn_clear_annotations.clicked.connect(self.btn_clear_annotations_clicked_slot)

    def btn_clear_annotations_clicked_slot(self):
        self.viewer.remove_annotations()

    def btn_enable_polygon_selection_clicked_slot(self):
        self.viewer.selection_mode=SELECTION_MODE.POLYGON

    def btn_enable_rectangle_selection_clicked_slot(self):
        self.viewer.selection_mode=SELECTION_MODE.BOX

    def btn_enable_none_selection_clicked_slot(self):
        self.viewer.selection_mode=SELECTION_MODE.NONE

    def btn_enable_free_selection_clicked_slot(self):
        self.viewer.selection_mode=SELECTION_MODE.FREE

    def save_annotations(self):
        scene: QGraphicsScene=self.viewer.scene()
        annot_list=[]
        for item in scene.items():
            img_bbox: QRectF=self.viewer.pixmap.sceneBoundingRect()
            offset=QPointF(img_bbox.width()/2,img_bbox.height()/2)
            if isinstance(item,EditableBox):
                item_box: QRectF=item.sceneBoundingRect()
                x1=math.floor(item_box.topLeft().x()+offset.x())
                y1=math.floor(item_box.topRight().y()+offset.y())
                x2=math.floor(item_box.bottomRight().x()+offset.x())
                y2=math.floor(item_box.bottomRight().y()+offset.y())
                box=AnnotaVO()
                box.label=item.label.id if item.label else None
                box.entry=self.source.id
                box.kind="box"
                box.points=",".join(map(str,[x1,y1,x2,y2]))
                annot_list.append(box)
            elif isinstance(item,EditablePolygon):
                points=[[math.floor(pt.x()+offset.x()),math.floor(pt.y()+offset.y())] for pt in item.points]
                points=np.asarray(points).flatten().tolist()
                poly=AnnotaVO()
                poly.label=item.label.id if item.label else None
                poly.entry=self.source.id
                poly.kind="polygon"
                poly.points=",".join(map(str,points))
                annot_list.append(poly)
        self._annot_dao.save(self.source.id, annot_list)

    def btn_save_annotations_clicked_slot(self):
        self.save_annotations()

    def _scene_item_added(self, item: QGraphicsItem):
        item.tag = self.source

    def bind(self):
        self.load_images()
        self.load_models()
        self.load_labels()
Exemple #48
0
 def addSongs(self, songs):
     d = DBRunnable(self, songs)
     QThreadPool.globalInstance().start(d)
Exemple #49
0
    def __init__(self,parent=None):
        super(ImageViewerWidget,self).__init__(parent)
        self.setupUi(self)
        self.viewer=ImageViewer()
        self.viewer.scene().itemAdded.connect(self._scene_item_added)
        self.center_layout.addWidget(self.viewer,0,0)

        # self._label_background=QLabel()
        # self._label_background.setFixedHeight(40)
        # image = GUIUtilities.get_image("label.png")
        # self._label_background.setPixmap(image.scaledToHeight(40))
        # self.center_layout.addWidget(self._label_background,0,0,QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)

        self._label=QLabel()
        self._label.setVisible(False)
        self._label.setMargin(5)
        self._label.setStyleSheet('''
            QLabel{
            font: 12pt;
            border-radius: 25px;
            margin: 10px;
            color: black; 
            background-color: #FFFFDC;
            }
        ''')
        shadow=QGraphicsDropShadowEffect(self)
        shadow.setBlurRadius(8)
        # shadow.setColor(QtGui.QColor(76,35,45).lighter())
        shadow.setColor(QtGui.QColor(94, 93, 90).lighter())
        shadow.setOffset(2)
        self._label.setGraphicsEffect(shadow)
        self.center_layout.addWidget(self._label,0,0,QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)

        self.actions_layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter)
        self.actions_layout.setContentsMargins(0,5,0,0)
        self._ds_dao =  DatasetDao()
        self._hub_dao = HubDao()
        self._labels_dao = LabelDao()
        self._annot_dao = AnnotaDao()
        self._thread_pool=QThreadPool()
        self._loading_dialog=QLoadingDialog()
        self._source = None
        self._image = None
        self.images_list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection )
        #self.images_list_widget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.images_list_widget.currentItemChanged.connect(self.image_list_sel_changed_slot)
        self.images_list_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.images_list_widget.customContextMenuRequested.connect(self.image_list_context_menu)

        self.treeview_models=ModelsTreeview()
        self.treeview_models.setColumnWidth(0,300)
        self.tree_view_models_layout.addWidget(self.treeview_models)
        self.treeview_models.action_click.connect(self.trv_models_action_click_slot)

        self.treeview_labels = LabelsTableView()
        self.treeview_labels.action_click.connect(self.trv_labels_action_click_slot)
        self.tree_view_labels_layout.addWidget(self.treeview_labels)
        self.treeview_labels.selectionModel().selectionChanged.connect(self.default_label_changed_slot)
        #window = GUIUtilities.findMainWindow()
        #window.keyPressed.connect(self.window_keyPressEvent)
        self.create_actions_bar()
Exemple #50
0
class SomeObjectToDoComplicatedStuff(QRunnable):
    def __init__(self, name):
        QRunnable.__init__(self)
        self.name = name

    def run(self):
        print('running', self.name)
        a = 10
        b = 30
        c = 0
        for i in range(5000000):
            c += a**b
        print('done', self.name)


pool = QThreadPool.globalInstance()
pool.setMaxThreadCount(10)

batch_size = 100

workers = [None] * batch_size

for i in range(batch_size):
    worker = SomeObjectToDoComplicatedStuff('object ' + str(i))
    workers[i] = worker
    pool.start(worker)

print('All cued')
pool.waitForDone()

# processing the results back
Exemple #51
0
 def __init__(self):
     super().__init__()
     self.threadpool = QThreadPool()
     self.threadpool.globalInstance()
     poolnum = tool.loadJsons(tool.setting_address)[0]['pool_num']
     self.threadpool.setMaxThreadCount(int(poolnum))
Exemple #52
0
 def deffer_to_thread(self, cb, *args, **kwargs):
     args = (self, ) + args
     thread = Thread(self, cb, *args, **kwargs)
     QThreadPool.globalInstance().start(thread)
Exemple #53
0
 def start(self, action, data=None):
     QThreadPool.globalInstance().start(
         PugdebugAsyncTask(self, action, data)
     )