Exemplo n.º 1
0
class Table(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Table, self).__init__(parent)
        self.centralwidget = QtWidgets.QWidget(self)

        self.view = QTableView(self.centralwidget)
        self.comboBox = QtWidgets.QComboBox()

        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)

        self.gridLayout.addWidget(self.view, 1, 0, 1, 3)

        self.setCentralWidget(self.centralwidget)

        self.model = QtGui.QStandardItemModel(self)
        self.data = [("Йода.mp3", "dsad", "ddd", ' ', ' '),
                     ('d', 'asd', '1', "asdas", "asdasd"),
                     ("ddd", 'asd', '1', "asdas", "asdasd"),
                     ("ww", 'asd', '1', "asdas", "asdasd")]
        for rowName in self.data:
            self.model.invisibleRootItem().appendRow(
                [QtGui.QStandardItem(rowName[column]) for column in range(5)])

        self.model.setHorizontalHeaderLabels([
            'Название', 'Жанр', 'Автор', 'Дата создания', 'Альбом',
            'Скачать музыку', 'Удальть музыку'
        ])

        self.proxy = QtCore.QSortFilterProxyModel(self)
        self.proxy.setSourceModel(self.model)

        self.view.setModel(self.proxy)

        self.comboBox.addItems(
            ["Column {0}".format(x) for x in range(self.model.columnCount())])
        self.buttonGroup = QButtonGroup(self)
        self.buttonGroupDelete = QButtonGroup(self)
        row = 0
        flag = False

        for tup in self.data:
            col = 0
            for item in tup:
                cellinfo = QTableWidgetItem(item)
                cellinfo.setFlags(QtCore.Qt.ItemIsSelectable
                                  | QtCore.Qt.ItemIsEnabled)
                if (flag == False and col > 3):
                    button = QPushButton("Скачать")
                    self.buttonGroup.addButton(button, row)
                    self.view.setIndexWidget(self.proxy.index(row, 5), button)
                    flag = True

                col += 1
            flag = False
            row += 1
        self.buttonGroup.buttonClicked[int].connect(self.copyMusic)

        row = 0
        flag = False
        #
        for tup in self.data:
            col = 0
            for item in tup:
                cellinfo = QTableWidgetItem(item)
                cellinfo.setFlags(QtCore.Qt.ItemIsSelectable
                                  | QtCore.Qt.ItemIsEnabled)
                if (flag == False and col > 3):
                    button = QPushButton("Удалить")
                    self.buttonGroupDelete.addButton(button, row)
                    self.view.setIndexWidget(self.proxy.index(row, 6), button)
                    flag = True

                col += 1
            flag = False
            row += 1
        self.buttonGroupDelete.buttonClicked[int].connect(self.copyMusic)
        # self.lineEdit.textChanged.connect(self.on_lineEdit_textChanged)
        # self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged)
        #
        self.horizontalHeader = self.view.horizontalHeader()
        self.horizontalHeader.sectionClicked.connect(
            self.on_view_horizontalHeader_sectionClicked)

    @QtCore.pyqtSlot(int)
    def on_view_horizontalHeader_sectionClicked(self, logicalIndex):

        self.logicalIndex = logicalIndex
        self.menuValues = QtWidgets.QMenu(self)
        self.signalMapper = QtCore.QSignalMapper(self)
        self.comboBox.blockSignals(True)
        self.comboBox.setCurrentIndex(self.logicalIndex)
        self.comboBox.blockSignals(True)

        valuesUnique = [
            self.model.item(row, self.logicalIndex).text()
            for row in range(self.model.rowCount())
        ]
        actionAll = QtWidgets.QAction("All", self)
        actionAll.triggered.connect(self.on_actionAll_triggered)
        self.menuValues.addAction(actionAll)
        self.menuValues.addSeparator()
        for actionNumber, actionName in enumerate(
                sorted(list(set(valuesUnique)))):
            action = QtWidgets.QAction(actionName, self)
            self.signalMapper.setMapping(action, actionNumber)
            action.triggered.connect(self.signalMapper.map)
            self.menuValues.addAction(action)
        self.signalMapper.mapped.connect(self.on_signalMapper_mapped)
        headerPos = self.view.mapToGlobal(self.horizontalHeader.pos())
        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(
            self.logicalIndex)

        self.menuValues.exec_(QtCore.QPoint(posX, posY))

    @QtCore.pyqtSlot()
    def on_actionAll_triggered(self):
        filterColumn = self.logicalIndex
        filterString = QtCore.QRegExp("", QtCore.Qt.CaseInsensitive,
                                      QtCore.QRegExp.RegExp)

        self.proxy.setFilterRegExp(filterString)
        self.proxy.setFilterKeyColumn(filterColumn)

    @QtCore.pyqtSlot(int)
    def on_signalMapper_mapped(self, i):
        stringAction = self.signalMapper.mapping(i).text()
        filterColumn = self.logicalIndex
        filterString = QtCore.QRegExp(stringAction, QtCore.Qt.CaseSensitive,
                                      QtCore.QRegExp.FixedString)

        self.proxy.setFilterRegExp(filterString)
        self.proxy.setFilterKeyColumn(filterColumn)

    @QtCore.pyqtSlot(str)
    def on_lineEdit_textChanged(self, text):
        search = QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive,
                                QtCore.QRegExp.RegExp)

        self.proxy.setFilterRegExp(search)

    @QtCore.pyqtSlot(int)
    def on_comboBox_currentIndexChanged(self, index):
        self.proxy.setFilterKeyColumn(index)

    def copyMusic(self, row):
        self.nameMusic = self.view.indexAt(QPoint(0, 30 * row)).data(
            Qt.DisplayRole)
        self.albumMusic = self.view.indexAt(QPoint(400, 30 * row)).data(
            Qt.DisplayRole)
        self.dirlist = QFileDialog.getExistingDirectory(
            self, "Выбрать папку", ".")
        if self.dirlist != "":
            if (str(self.albumMusic) != ' ' and str(self.albumMusic) != ''):
                shutil.copy(
                    "C:\\" + self.albumMusic + '\\' + self.nameMusic,
                    # место "E:\\"+self.albumMusic+'\\'+self.nameMusic
                    str(self.dirlist))  # написать директорию с музыкой
            else:
                shutil.copy("C:\\" + self.nameMusic, str(self.dirlist))

    def deleteMusic(self, row):
        self.nameMusic = self.view.indexAt(QPoint(0, 30 * row)).data(
            Qt.DisplayRole)
        self.albumMusic = self.view.indexAt(QPoint(400, 30 * row)).data(
            Qt.DisplayRole)
Exemplo n.º 2
0
class PacketListWidget(QWidget):
    on_data_selected = pyqtSignal(QObject)

    def __init__(self):
        super().__init__()
        self.dv = None
        self.initUI()

    def showData(self, data):
        if not self.dv:
            self.dv = DynamicDataWidget()
            self.dv.setWindowTitle("Data view")
        self.dv.setContents(data)
        self.dv.show()

    def initUI(self):
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        #tabs = QTabWidget()
        #layout.addWidget(tabs)

        self.packetlist = QTableView()
        self.packetlist.setSortingEnabled(True)
        self.packetlist.setContextMenuPolicy(Qt.CustomContextMenu)
        self.packetlist.customContextMenuRequested.connect(
            self.onPacketlistContextMenu)
        self.packetlist.horizontalHeader().setContextMenuPolicy(
            Qt.CustomContextMenu)
        self.packetlist.horizontalHeader().customContextMenuRequested.connect(
            self.onHeaderContextMenu)
        self.packetlist.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.packetlistmodel = PacketListModel()
        #self.packetlistmodel.rowsInserted.connect(lambda a,b,c: tabs.setTabText(0, "Raw Frames (%d)"%self.packetlistmodel.rowCount(QModelIndex())))
        self.packetlist.setModel(self.packetlistmodel)
        self.packetlist.selectionModel().selectionChanged.connect(
            self.onPacketlistSelectionChanged)
        self.packetlist.selectionModel().currentChanged.connect(
            self.onPacketlistCurrentChanged)
        #tabs.addTab(self.packetlist, "Raw Frames")
        layout.addWidget(self.packetlist)

    def setContents(self, lstObj):
        self.listObject = lstObj
        print("PacketListWidget::setContents", lstObj, len(lstObj))
        self.setWindowTitle(str(lstObj))
        #for bbuf in lstObj.buffers:
        #    self.addPacketToList(bbuf)
        self.packetlistmodel.setList(self.listObject)

    def onPacketlistSelectionChanged(self, selected, deselected):
        pass

    def onPacketlistCurrentChanged(self, current, previous):
        if current.isValid():
            bbuf = self.listObject.buffers[current.row()]
            self.on_data_selected.emit(bbuf)

    def onPacketlistContextMenu(self, point):
        index = self.packetlist.indexAt(point)
        ctx = QMenu("Context menu", self.packetlist)
        if index.isValid():
            bbuf = self.listObject.buffers[index.row()]
            ctx.addAction("Item details", lambda: self.showData(bbuf))
            ctx.addSeparator()
        ctx.addAction("Select all", lambda: self.packetlist.selectAll())

        ctx.exec(self.packetlist.viewport().mapToGlobal(point))

    def onHeaderContextMenu(self, point):
        index = self.packetlist.horizontalHeader().logicalIndexAt(point)
        print(index)

        ctx = QMenu("Context menu", self.packetlist)
        if index > -1:
            ctx.addAction("Header " + str(index))
            ctx.addAction("Edit", lambda: self.onEditColumn(index))
            ctx.addAction("Remove column",
                          lambda: self.packetlistmodel.removeColumn(index))
            ctx.addSeparator()
        addIdx = None if index == -1 else index
        ctx.addAction("Add column ...", lambda: self.onAddColumn(addIdx))
        for key in self.listObject.getAllKeys(metadataKeys=True,
                                              fieldKeys=False):
            ctx.addAction(key,
                          lambda key=key: self.packetlistmodel.addColumn(
                              ColumnInfo(key, src="meta"), addIdx))
        ctx.addSeparator()
        for key in self.listObject.getAllKeys(metadataKeys=False,
                                              fieldKeys=True):
            ctx.addAction(key,
                          lambda key=key: self.packetlistmodel.addColumn(
                              ColumnInfo(key, src="field"), addIdx))

        ctx.exec(self.packetlist.horizontalHeader().mapToGlobal(point))

    def getColumnInfoDefinition(self):
        return [
            ("key", "Key", "text", {
                "autocomplete": self.listObject.getAllKeys()
            }),
            ("title", "Column title", "text", {}),
            ("src", "Data source", "select", {
                "options": [("meta", "Packet meta data"),
                            ("field", "Packet field")]
            }),
            ("show", "Display mode", "select", {
                "options": [("show", "Display contents"),
                            ("showname", "Tree display contents"),
                            ("hex", "Hex value")]
            }),
        ]

    def onAddColumn(self, insertBefore):
        par = showSettingsDlg(self.getColumnInfoDefinition())
        if par is not None:
            if par["title"] == "": par["title"] = par["key"]
            self.packetlistmodel.addColumn(ColumnInfo(**par), insertBefore)

    def onEditColumn(self, index):
        par = showSettingsDlg(self.getColumnInfoDefinition(),
                              self.packetlistmodel.columns[index].toDict())
        if par is not None:
            if par["title"] == "": par["title"] = par["key"]
            self.packetlistmodel.removeColumn(index)
            self.packetlistmodel.addColumn(ColumnInfo(**par), index)

    def run_ndis(self):
        pass

    def addPacketToList(self, bbuf):
        idx = self.packetlist.rowCount()
        self.packetlist.insertRow(idx)
        c = 0
        #print(bbuf.ranges)
        for k, v in bbuf.metadata.items():
            #print(k,v)
            self.packetlist.setItem(idx, c, QTableWidgetItem(str(v)))
            c += 1
            if c > 10: break
        for rr in bbuf.ranges:
            #print(rr)
            self.packetlist.setItem(idx, c, QTableWidgetItem(str(rr.metadata)))
            c += 1
            if c > 10: break
Exemplo n.º 3
0
class FileManager(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self)
        self.parent = parent
        self.name = 'File Manager'
        self.port = '9080'
        self.server = None

        drives = win32api.GetLogicalDriveStrings().split('\\\000')[:-1]
        self.logical_drives = drives + [d+'/' for d in drives]
        # create file manager tab
        self.file_manager_layout = QGridLayout(self)

        # create left manager (PC)
        self.left_up_btn = QPushButton()
        self.left_up_btn.setIcon(QIcon('images/up_btn.png'))
        self.left_up_btn.setFixedWidth(25)
        self.file_manager_layout.addWidget(self.left_up_btn, 0, 0, 1, 1)

        self.left_dir_path = QLineEdit(self.parent.expanduser_dir)
        self.file_manager_layout.addWidget(self.left_dir_path, 0, 1, 1, 8)

        self.left_go_to_btn = QPushButton()
        self.left_go_to_btn.setIcon(QIcon('images/right_btn.png'))
        self.left_go_to_btn.setFixedWidth(25)
        self.file_manager_layout.addWidget(self.left_go_to_btn, 0, 9, 1, 1)

        self.lefttableview = QTableView()
        self.lefttableview.setSelectionBehavior(QTableView.SelectRows)
        self.lefttableview.verticalHeader().hide()
        self.lefttableview.setShowGrid(False)
        self.lefttableview.contextMenuEvent = lambda event: self.left_context(event)

        self.left_file_model = QFileSystemModel()
        self.left_file_model.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.left_file_model.setRootPath(self.parent.expanduser_dir)
        self.left_file_model_path = self.parent.expanduser_dir
        self.lefttableview.setModel(self.left_file_model)
        self.lefttableview.setColumnWidth(0, 150)
        self.lefttableview.setRootIndex(self.left_file_model.index(self.parent.expanduser_dir))
        self.file_manager_layout.addWidget(self.lefttableview, 1, 0, 5, 10)

        # central buttons
        self.download_file_from_device_btn = QPushButton()
        self.download_file_from_device_btn.setIcon(QIcon('images/left_btn.png'))
        self.download_file_from_device_btn.setFixedWidth(30)
        self.download_file_from_device_btn.setEnabled(False)
        self.upload_file_to_device_btn = QPushButton()
        self.upload_file_to_device_btn.setIcon(QIcon('images/right_btn.png'))
        self.upload_file_to_device_btn.setFixedWidth(30)
        self.upload_file_to_device_btn.setEnabled(False)
        self.delete_file_btn = QPushButton()
        self.delete_file_btn.setIcon(QIcon('images/delete_btn.png'))
        self.delete_file_btn.setFixedWidth(30)
        self.file_manager_layout.addWidget(self.download_file_from_device_btn, 3, 10, 1, 1)
        self.file_manager_layout.addWidget(self.delete_file_btn, 4, 10, 1, 1)

        # create right manager (Device)
        self.right_up_btn = QPushButton()
        self.right_up_btn.setIcon(QIcon('images/up_btn.png'))
        self.right_up_btn.setFixedWidth(25)
        self.right_up_btn.setEnabled(False)
        self.file_manager_layout.addWidget(self.right_up_btn, 0, 11, 1, 1)

        self.add_folder_btn = QPushButton()
        self.add_folder_btn.setIcon(QIcon('images/folder_add.png'))
        self.add_folder_btn.setFixedWidth(25)
        self.add_folder_btn.setToolTip(_('Add new folder'))
        self.add_folder_btn.setEnabled(False)
        self.file_manager_layout.addWidget(self.add_folder_btn, 0, 12, 1, 1)

        self.right_dir_path = QLineEdit()
        self.file_manager_layout.addWidget(self.right_dir_path, 0, 13, 1, 7)

        self.right_update_btn = QPushButton()
        self.right_update_btn.setIcon(QIcon('images/update.png'))
        self.right_update_btn.setFixedWidth(25)
        self.file_manager_layout.addWidget(self.right_update_btn, 0, 20, 1, 1)

        self.righttableview = QTableView()
        self.righttableview.setSelectionBehavior(QTableView.SelectRows)
        self.righttableview.contextMenuEvent = lambda event: self.right_context(event)
        self.righttableview.verticalHeader().hide()
        self.righttableview.setShowGrid(False)
        self.right_file_model = QStandardItemModel()
        self.right_file_model_path = []
        self.right_active_dir = None
        self.righttableview.setModel(self.right_file_model)
        self.file_manager_layout.addWidget(self.righttableview, 1, 11, 5, 10)

        # auto sync
        self.timer = QTimer()
        self.timer.setInterval(10000)
        self.file_models_auto_sync = QCheckBox(_('Auto sync'))
        self.left_file_model_auto_sync_label = QLineEdit()
        self.left_file_model_auto_sync_label.setReadOnly(True)
        self.right_file_model_auto_sync_label = QLineEdit()
        self.right_file_model_auto_sync_label.setReadOnly(True)
        self.file_manager_layout.addWidget(self.file_models_auto_sync, 6, 9, 1, 3, alignment=Qt.AlignCenter)
        self.file_manager_layout.addWidget(self.left_file_model_auto_sync_label, 6, 0, 1, 9)
        self.file_manager_layout.addWidget(self.right_file_model_auto_sync_label, 6, 12, 1, 9)

        self.timer.timeout.connect(lambda: self.check_device_sync())
        self.lefttableview.clicked.connect(lambda idx: self.left_file_model_clicked(idx))
        self.lefttableview.doubleClicked.connect(lambda idx: self.left_file_model_doubleclicked(idx))
        self.left_up_btn.clicked.connect(lambda: self.left_file_model_up(self.left_file_model.index(self.left_dir_path.text())))
        self.left_go_to_btn.clicked.connect(lambda: self.left_file_model_go_to_dir())

        self.right_update_btn.clicked.connect(lambda: self.right_file_model_update())
        self.righttableview.doubleClicked.connect(lambda idx: self.right_file_model_doubleclicked(idx))
        self.right_up_btn.clicked.connect(lambda: self.right_file_model_up())
        self.add_folder_btn.clicked.connect(lambda: self.right_file_model_add_folder())
        self.righttableview.clicked.connect(lambda idx: self.right_file_model_clicked(idx))
        self.download_file_from_device_btn.clicked.connect(lambda: self.download_file_from_device())
        self.upload_file_to_device_btn.clicked.connect(lambda: self.upload_file_to_device())
        self.delete_file_btn.clicked.connect(lambda: self.delete_file_from_file_model())

        self.parent.settings_widget.signal_ip_changed.connect(lambda ip: self.change_ip(ip))

        self.parent.signal_language_changed.connect(lambda: self.retranslate())

    def retranslate(self):
        self.file_models_auto_sync.setText(_('Auto sync'))
        self.right_file_model.setHorizontalHeaderLabels([_('Name'), _('Size'), _('Changed date')])

    def change_ip(self, ip):
        self.server = ':'.join([ip, self.port])
        self.right_file_model_path = []
        self.right_file_model.clear()

    def left_file_model_clicked(self, idx):
        if os.path.isfile(self.left_file_model.filePath(idx)) and self.parent.geoshark_widget.device_on_connect:
            self.upload_file_to_device_btn.setEnabled(True)
        else:
            self.upload_file_to_device_btn.setEnabled(False)

    def left_file_model_doubleclicked(self, idx):
        self.left_up_btn.setEnabled(True)
        fileinfo = self.left_file_model.fileInfo(idx)
        if fileinfo.isDir():
            self.lefttableview.setRootIndex(idx)
            self.left_dir_path.setText(self.left_file_model.filePath(idx))
            self.left_file_model_path = self.left_file_model.filePath(idx)

    def left_file_model_up(self, idx):
        self.upload_file_to_device_btn.setEnabled(False)
        if self.left_dir_path.text() in self.logical_drives:
            self.left_file_model = QFileSystemModel()
            self.left_file_model.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
            self.left_file_model.setRootPath('')
            self.lefttableview.setModel(self.left_file_model)
            self.left_dir_path.setText('My computer')
            self.left_up_btn.setEnabled(False)
        else:
            fileinfo = self.left_file_model.fileInfo(idx)
            dir = fileinfo.dir()
            self.left_dir_path.setText(dir.path())
            self.left_file_model_path = dir.path()
            self.lefttableview.setRootIndex(self.left_file_model.index(dir.absolutePath()))

    def left_file_model_go_to_dir(self):
        if os.path.isdir(self.left_dir_path.text()):
            self.left_file_model_path = self.left_dir_path.text()
            self.left_up_btn.setEnabled(True)
            self.upload_file_to_device_btn.setEnabled(False)
            self.left_file_model.setRootPath(self.left_dir_path.text())
            self.lefttableview.setRootIndex(self.left_file_model.index(self.left_dir_path.text()))

    def right_file_model_update(self):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        url = 'http://{}/active_dir'.format(self.server)
        try:
            res = requests.get(url, timeout=5)
            if res.ok:
                self.right_active_dir = res.text
        except requests.exceptions.RequestException:
            pass

        file_list = self.get_folder_list()
        if file_list is None:
            return
        self.fill_right_file_model(file_list)
        self.download_file_from_device_btn.setEnabled(False)

    def get_folder_list(self, folder_path=None):
        if self.server is None:
            return
        if folder_path is None:
            folder_path = '/'.join(self.right_file_model_path)
        url = 'http://{}/data/{}'.format(self.server, folder_path)
        try:
            res = requests.get(url, timeout=1)
        except requests.exceptions.RequestException:
            show_error(_('GeoShark error'), _('GeoShark is not responding.'))
            return
        if res.ok:
            res = res.json()
            return res
        else:
            return None

    def check_device_sync(self):
        pc_path = self.left_file_model_auto_sync_label.text()
        device_path = self.right_file_model_auto_sync_label.text()
        if self.file_models_auto_sync.isChecked() and pc_path != '' and device_path != '':
            file_list = self.get_folder_list(self.right_file_model_auto_sync_label.text())
            left_list_of_files = os.listdir(self.left_file_model_auto_sync_label.text())
            for f in file_list:
                if f['name'] not in left_list_of_files or os.path.getsize('{}/{}'.format(pc_path, f['name'])) != f['size']:
                    self.download_file_from_device(device_path='{}/{}'.format(device_path, f['name']),
                                                   pc_path=pc_path)

    def fill_right_file_model(self, directory):
        self.add_folder_btn.setEnabled(True)
        if len(self.right_file_model_path) < 1:
            self.right_up_btn.setEnabled(False)
        else:
            self.right_up_btn.setEnabled(True)
            self.add_folder_btn.setEnabled(False)
        self.right_file_model.removeRows(0, self.right_file_model.rowCount())
        self.right_dir_path.setText('/'.join(self.right_file_model_path))
        self.right_file_model.setHorizontalHeaderLabels([_('Name'), _('Size'), _('Changed date')])
        for row, instance in enumerate(directory):
            if instance['name'] == self.right_active_dir:
                image = QIcon('images/directory_active.png')
            else:
                image = QIcon('images/{}.png'.format(instance['type']))
            item = QStandardItem(image, instance['name'])
            item.setData(instance['type'], 5)
            item.setEditable(False)
            self.right_file_model.setItem(row, 0, item)
            item = QStandardItem(str(instance['size']))
            item.setEditable(False)
            self.right_file_model.setItem(row, 1, item)
            item = QStandardItem(str(datetime.datetime.fromtimestamp(instance['changed']).strftime('%d.%m.%Y %H:%M')))
            item.setEditable(False)
            self.right_file_model.setItem(row, 2, item)

        self.righttableview.setColumnWidth(0, max(150, self.righttableview.columnWidth(0)))

    def left_context(self, event):
        context_menu = {}
        index = self.lefttableview.indexAt(event.pos())
        if index.row() == -1:
            return
        context_menu[_('Set active directory')] = lambda: self.set_pc_active_directory(self.left_file_model.filePath(index))
        context_menu[_('Remove element')] = lambda: self.delete_file_from_file_model(index)

        if not self.left_file_model.isDir(index):
            del context_menu[_('Set active directory')]

        menu = QMenu()

        actions = [QAction(a) for a in context_menu.keys()]
        menu.addActions(actions)
        action = menu.exec_(event.globalPos())
        if action:
            context_menu[action.text()]()

    def set_pc_active_directory(self, path):
        self.left_file_model_auto_sync_label.setText(path)
        self.parent.settings_widget.left_folder_tracked.setText(path)

    def right_context(self, event):
        context_menu = {}

        index = self.righttableview.indexAt(event.pos())
        if index.row() == -1:
            return
        item = self.right_file_model.itemFromIndex(index)
        item_row = item.row()

        context_menu[_('Set active directory')] = lambda: self.set_active_directory(item)
        context_menu[_('Remove element')] = lambda: self.delete_file_from_file_model(index)

        if self.right_file_model.item(item_row, 0).data(5) != 'directory':
            del context_menu[_('Set active directory')]

        menu = QMenu()

        actions = [QAction(a) for a in context_menu.keys()]
        menu.addActions(actions)
        action = menu.exec_(event.globalPos())
        if action:
            context_menu[action.text()]()

    def set_active_directory(self, item):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        dirname = item.text()
        url = 'http://{}/active_dir'.format(self.server)
        try:
            res = requests.post(url=url, data=dirname, timeout=5)
        except requests.exceptions.RequestException:
            show_error(_('GeoShark error'), _('Can not set active directory.\nGeoShark is not responding.'))
            return
        if res.ok:
            self.right_file_model_update()
            self.set_active_path(dirname)
        elif res.status_code == 400:
            show_error(_('GeoShark error'), _('Request declined - request body specifies invalid path.'))
            return
        elif res.status_code == 409:
            show_error(_('GeoShark error'), _('Request declined - switching active directory is forbidden during active session.'))
            return
        else:
            print(res.status_code)
            return

    def set_active_path(self, dirname):
        path = '/'.join(self.right_file_model_path + [dirname])
        self.parent.settings_widget.right_folder_tracked.setText(path)
        self.right_file_model_auto_sync_label.setText(path)

    def right_file_model_clicked(self, idx):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        if self.right_file_model.item(idx.row(), 0).data(5) == 'file':
            self.download_file_from_device_btn.setEnabled(True)
        else:
            self.download_file_from_device_btn.setEnabled(False)

    def right_file_model_doubleclicked(self, idx):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        model_path = '/'.join(self.right_file_model_path)
        idx_name = self.right_file_model.item(idx.row(), 0).text()
        if model_path != '':
            dir = '{}/{}'.format(model_path, idx_name)
        else:
            dir = '{}'.format(idx_name)

        file_list = self.get_folder_list(dir)
        if file_list is None:
            return
        self.right_file_model_path = dir.split('/')
        self.fill_right_file_model(file_list)

    def right_file_model_up(self):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        self.download_file_from_device_btn.setEnabled(False)
        up_dir = '/'.join(self.right_file_model_path[:-1])

        file_list = self.get_folder_list(up_dir)
        if file_list is None:
            return
        if up_dir == '':
            self.right_file_model_path = []
        else:
            self.right_file_model_path = up_dir.split('/')
        self.fill_right_file_model(file_list)

    def right_file_model_add_folder(self):
        if not self.parent.geoshark_widget.device_on_connect:
            return
        row = self.right_file_model.rowCount()
        item = QStandardItem(QIcon('images/folder.png'), 'New Directory')
        item.setData('directory', 5)
        item.setEditable(True)
        self.right_file_model.setItem(row, 0, item)
        item = QStandardItem(str(0.0))
        item.setEditable(False)
        self.right_file_model.setItem(row, 1, item)
        item = QStandardItem(str(datetime.datetime.today().strftime('%d.%m.%Y %H:%M')))
        item.setEditable(False)
        self.right_file_model.setItem(row, 2, item)

    def download_file_from_device(self, device_path=None, pc_path=None):
        if not self.parent.geoshark_widget.device_on_connect or self.server is None:
            return

        if not device_path:
            fileName = self.find_selected_idx()
            if fileName:
                fileName = fileName.data()
                device_path = '/'.join(self.right_file_model_path + [fileName])
            else:
                return

        right_file_model_filename = device_path.split('/')[-1]
        save_to_file = '{}/{}'.format(self.left_file_model_path, right_file_model_filename) \
            if not pc_path else '{}/{}'.format(pc_path, right_file_model_filename)
        if os.path.isfile(save_to_file):
            answer = show_warning_yes_no(_('File warning'), _('There is a file with the same name in PC.\n'
                                         'Do you want to rewrite <b>{}</b>?'.format(right_file_model_filename)))
            if answer == QMessageBox.No:
                return
        url = 'http://{}/data/{}'.format(self.server, device_path)
        try:
            b = bytearray()
            res = requests.get(url, timeout=5, stream=True)
            if res.ok:
                progress = QProgressBar()
                progress.setFormat(right_file_model_filename)
                self.file_manager_layout.addWidget(progress, 6, 12, 1, 9)
                total_length = int(res.headers.get('content-length'))
                len_b = 0
                for chunk in tee_to_bytearray(res, b):
                    len_b += len(chunk)
                    progress.setValue((len_b/total_length)*99)
                    QApplication.processEvents()
            else:
                return
        except:
            self.file_manager_layout.addWidget(self.right_file_model_auto_sync_label, 6, 12, 1, 9)
            show_error(_('GeoShark error'), _('GeoShark is not responding.'))
            return

        if res.ok:
            progress.setValue(100)

            with open(save_to_file, 'wb') as file:
                file.write(b)
        for i in reversed(range(self.file_manager_layout.count())):
            if isinstance(self.file_manager_layout.itemAt(i).widget(), QProgressBar):
                self.file_manager_layout.itemAt(i).widget().setParent(None)
        self.file_manager_layout.addWidget(self.right_file_model_auto_sync_label, 6, 12, 1, 9)

    def upload_file_to_device(self):
        if not self.parent.geoshark_widget.device_on_connect or self.server is None:
            return
        file = self.left_file_model.filePath(self.lefttableview.currentIndex())
        filename = file.split('/')[-1]
        url = 'http://{}/data/{}'.format(self.server, '/'.join(self.right_file_model_path))
        filesize = os.path.getsize(file)
        if filesize == 0:
            show_error(_('File error'), _('File size must be non zero.'))
            return
        progress = ProgressBar(text=_('Upload File Into GeoShark'), window_title=_('Upload file to GeoShark'))
        encoder = MultipartEncoder(
            fields={'upload_file': (filename, open(file, 'rb'))}  # added mime-type here
        )
        data = MultipartEncoderMonitor(encoder, lambda monitor: progress.update((monitor.bytes_read/filesize)*99))

        try:
            res = requests.post(url, data=data, headers={'Content-Type': encoder.content_type}, timeout=5)
        except requests.exceptions.RequestException:
            progress.close()
            show_error(_('GeoShark error'), _('GeoShark is not responding.'))
            return
        if res.ok:
            progress.update(100)
            self.right_file_model_update()

    def delete_file_from_file_model(self, index=None):
        selected = self.find_selected_idx()
        if index is None and selected is None:
            return
        if index is None:
            index = selected
        model = index.model()
        index_row = index.row()
        path = model.filePath(index) if hasattr(model, 'filePath') else model.index(index_row, 0).data()
        answer = show_warning_yes_no(_('Remove File warning'),
                                     _('Do you really want to remove:\n{}').format(path))
        if answer == QMessageBox.No:
            return

        if isinstance(model, QFileSystemModel):
            model.remove(index)

        elif isinstance(model, QStandardItemModel):
            if not self.parent.geoshark_widget.device_on_connect or self.server is None:
                return
            filename = self.right_file_model.item(index.row(), 0).text()
            path = '/'.join(self.right_file_model_path + [filename])

            url = 'http://{}/data/{}'.format(self.server, path)
            try:
                res = requests.delete(url)
            except requests.exceptions.RequestException:
                show_error(_('GeoShark error'), _('GeoShark is not responding.'))
                return
            if res.ok:
                self.right_file_model_update()
            elif res.status_code == 400:
                self.right_file_model.removeRow(index.row())
            elif res.status_code == 409:
                show_error(_('GeoShark error'),
                           _('Request declined - directory is the part of active session working directory.'))
                return

    def find_selected_idx(self):
        left_indexes = self.lefttableview.selectedIndexes()
        right_indexes = self.righttableview.selectedIndexes()
        if len(left_indexes) == 0 and len(right_indexes) == 0:
            return None
        index = left_indexes[0] if len(left_indexes) > len(right_indexes) else right_indexes[0]
        return index

    def save_file_models_folder(self):
        self.left_file_model_auto_sync_label.setText(self.parent.settings_widget.left_folder_tracked.text())
        self.right_file_model_auto_sync_label.setText(self.parent.settings_widget.right_folder_tracked.text())
Exemplo n.º 4
0
class ERUploaderWindow(QDialog):
    """This window provides the user a visual picture of the local and online status of the Extra Reflectance calibration file repository. It also allows uploading
    of files that are present locally but not on the server. It does not have good handling of edge cases, e.g. online server in inconsistent state."""
    def __init__(self, manager: ERManager, parent: Optional[QWidget] = None):
        self._dataComparator = ERDataComparator(manager.onlineDirectory,
                                                manager.localDirectory)
        self._manager = manager
        self._selectedId: str = None
        super().__init__(parent)
        self.setModal(False)
        self.setWindowTitle("Extra Reflectance File Manager")
        self.setLayout(QVBoxLayout())
        self.table = QTableView(self)
        self.fileStatus = self._dataComparator.compare()
        self.table.setModel(PandasModel(self.fileStatus))
        self.table.setSelectionMode(QTableView.SingleSelection)
        self.table.setSelectionBehavior(QTableView.SelectRows)
        self.table.customContextMenuRequested.connect(self.openContextMenu)
        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.uploadButton = QPushButton("Upload to Drive")
        self.uploadButton.released.connect(self._updateGDrive)
        self.uploadButton.setToolTip(
            "Upload any files for which the status is `Local Only` to the google drive account."
        )
        self.refreshButton = QPushButton('Refresh')
        self.refreshButton.setToolTip(
            "Rescan the files in the applications data directory.")
        self.refreshButton.released.connect(self.refresh)
        self.updateIndexButton = QPushButton("Update Index File")
        self.updateIndexButton.setToolTip(
            "Download the online index file and merge it with our local index file."
        )
        self.updateIndexButton.released.connect(self._updateIndexFile)
        self.layout().addWidget(self.table)
        l = QHBoxLayout()
        l.setContentsMargins(0, 0, 0, 0)
        l.addWidget(self.uploadButton)
        l.addWidget(self.updateIndexButton)
        l.addWidget(self.refreshButton)
        w = QWidget()
        w.setLayout(l)
        self.layout().addWidget(w)
        self.table.setColumnWidth(0, 300)
        self.table.setColumnWidth(1, 150)
        self.table.setColumnWidth(2, 150)
        self.table.setMinimumWidth(
            sum(
                self.table.columnWidth(i)
                for i in range(self.table.model().columnCount())) +
            self.table.verticalHeader().width() + 20)

    def displayInfo(self, index: QModelIndex):
        msg = QMessageBox.information(self, 'Info',
                                      repr(self.fileStatus.iloc[index.row()]))

    def plotData(self, index: QModelIndex):
        idTag = self.fileStatus.iloc[index.row()]['idTag']
        md = self._dataComparator.local.getMetadataFromId(idTag)
        erCube = ExtraReflectanceCube.fromMetadata(md)
        self.plotHandle = PlotNd(erCube.data)

    def openContextMenu(self, pos: QPoint):
        """This method opens a context menu, it should be called when the user right clicks."""
        index = self.table.indexAt(pos)
        row = self.fileStatus.iloc[index.row()]
        menu = QMenu()
        displayAction = QAction("Display Info")
        displayAction.triggered.connect(lambda: self.displayInfo(index))
        menu.addAction(displayAction)
        if row['Local Status'] == self._dataComparator.local.DataStatus.found.value:
            plotAction = QAction("Plot Local Data")
            plotAction.triggered.connect(lambda: self.plotData(index))
            menu.addAction(plotAction)
        menu.exec(self.mapToGlobal(pos))

    def _updateGDrive(self):
        """Checks for all files taht are present locally but not on the server. Uploads those file and then overwrites the index."""
        try:
            status = self.fileStatus
            if not np.all((status['Index Comparison'] ==
                           ERDataComparator.ComparisonStatus.LocalOnly.value)
                          | (status['Index Comparison'] ==
                             ERDataComparator.ComparisonStatus.Match.value)):
                raise ValueError(
                    "Uploading cannot be performed if the local index file is not valid. Try updating the index file."
                )
            uploadableRows = (
                status['Index Comparison']
                == ERDataComparator.ComparisonStatus.LocalOnly.value) | (
                    status['Online Status']
                    == ERDataDirectory.DataStatus.missing.value)
            if np.any(uploadableRows):  # There is something to upload
                for i, row, in status.loc[uploadableRows].iterrows():
                    fileName = [
                        i.fileName
                        for i in self._dataComparator.local.index.cubes
                        if i.idTag == row['idTag']
                    ][0]
                    self._manager.upload(fileName)
                self._manager.upload('index.json')
            self.refresh()
        except Exception as e:
            logger = logging.getLogger(__name__)
            logger.exception(e)
            mess = QMessageBox.information(self, 'Sorry', str(e))

    def refresh(self):
        """Scans local and online files to refresh the display."""
        self._dataComparator.updateIndexes()
        self.fileStatus = self._dataComparator.compare()
        self.table.setModel(PandasModel(self.fileStatus))

    def _updateIndexFile(self):
        self._dataComparator.online.updateIndex()
        index = ERIndex.merge(self._dataComparator.local.index,
                              self._dataComparator.online.index)
        self._dataComparator.local.saveNewIndex(index)
        self.refresh()
Exemplo n.º 5
0
class CustomTableWidget(QWidget):
    """
    DESCRIPTION
    -----------
    This is custom table widget.
    Public functions:
    1) populate(data: ndarray or hdf5)

    Public slots:
    1) fill_results(text: str, data: ndarray or hdf5) -> filling the cells
    2) draw_plot(data: ndarray of hdf5) -> creates plot by 2 selected sections in table
    """
    def __init__(self, model=None):
        super().__init__()

        # create the table
        self.table = QTableView(self)
        self.table.resizeColumnsToContents()

        # defining the model
        if model is None:
            self.model = QStandardItemModel()
        else:
            self.model = model

        # setting model to the table
        self.table.setModel(self.model)

        # disable edit on cells
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        # layout setting for widget
        self.myLay = QVBoxLayout()
        self.myLay.addWidget(self.table)
        self.setLayout(self.myLay)

    def __paint_column(self, data):
        """
        DESCRIPTION
        -----------
        This is private function for painting cells.
        If value of cell is postive -> red cell, otherwise it will be painted to green.
        """
        for i in range(len(data[:, 0])):
            if data[:, 0][i] >= 0:
                self.model.setData(self.model.index(i, 0), QBrush(Qt.red),
                                   QtCore.Qt.BackgroundRole)
            else:
                self.model.setData(self.model.index(i, 0), QBrush(Qt.green),
                                   QtCore.Qt.BackgroundRole)

    def populate(self, data=None):
        """
        This function fills the table depending on the data that was passed to it.
        Additionally, two columns are created to display aggregation results.
        The last column displays the sum of the rows in each cell.
        The penultimate is the sum of columns in each cell of the column.
        """

        # clear the model data
        self.table.model().clear()

        # setting value from data to each cell
        for i in range(len(data)):
            row = []
            for j in range(len(data[i] + 2)):
                if j < len(data) - 1:
                    cell = QStandardItem(str(data[i][j]))
                else:
                    cell = QStandardItem('0')
                row.append(cell)
            self.model.appendRow(row)

        # adding QComboBox to each cell in the last column
        for row in range(len(data)):
            c = QComboBox()
            c.addItems([
                '1',
                '2',
                '3',
                '4',
                '5',
            ])

            # getting the indexes in the table
            i = self.table.model().index(row, len(data[row]) - 1)

            # setting the QComboBox by index
            self.table.setIndexWidget(i, c)

            # setting the default QComboBox text if it in (0, 5]
            if 0 < data[row, -1] <= 5:
                self.table.indexWidget(i).setCurrentIndex(data[row, -1] - 1)
                self.model.setData(i, self.table.indexWidget(i).currentText())

            # filling the results columns
            data[row, -1] = int(c.currentText())
            self.model.setItem(row,
                               len(data[row]) + 1,
                               QStandardItem(str(np.sum(data[row]))))
            self.model.setItem(row, len(data[row]),
                               QStandardItem(str(np.sum(data[:, row]))))

            # connecting to slot when text is changed
            self.table.indexWidget(i).currentTextChanged.connect(
                lambda text: self.fill_results(data, text))

        # painting the first column
        self.__paint_column(data)

        # drawing plot when sections clicked
        self.table.horizontalHeader().sectionClicked.connect(
            lambda arg: self.draw_plot(arg, data))

    def fill_results(self, data, text):
        """This function is PyQT slot and fills the last column of the table
           filling rule: sum
        """

        # calling the sender
        widget = self.sender()

        # getting table row and column by widget position in QTableView
        index = self.table.indexAt(widget.pos())
        row = index.row()
        column = index.column()

        # filling cells in last column
        data[row, -1] = int(text)
        self.model.setItem(row,
                           len(data[row]) + 1,
                           QStandardItem(str(np.sum(data[row]))))

        # filling cells in penult column (each cell rule: sum of columns)
        max_rows = len(data) - 1
        self.model.setItem(max_rows, column + 1,
                           QStandardItem(str(np.sum(data[:, column]))))

    def draw_plot(self, *args):
        """
        This function is PyQT slot. Draws plot by given data
        """
        # preventing results columns drawing
        try:
            cols = []

            # getting selected columns
            indexes = self.table.selectionModel().selectedColumns(0)
            for index in indexes:
                col = index.column()
                cols.append(col)

            # drawing a plot
            if (len(cols) > 1) and (cols[0] != cols[-1]):
                x = args[1][:, cols[0]]
                y = args[1][:, cols[-1]]

                self.parent().guiplot.clear()
                self.parent().guiplot.plot(x, y)
        except:
            pass
Exemplo n.º 6
0
class MainWindow1(QMainWindow, MainWindowUI):
    # Переопределяем конструктор класса
    def __init__(self):
        # Обязательно нужно вызвать метод супер класса
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(608, 684))
        self.previousClick = 0
        self.selected = []
        selectBtn = QPushButton('Select', self)
        selectBtn.move(10,10)
        restartBtn = QPushButton('Restart', self)
        restartBtn.move(30, 30)

        central_widget = QWidget(self)  # Создаём центральный виджет
        self.setCentralWidget(central_widget)  # Устанавливаем центральный виджет
        grid_layout = QGridLayout()  # Создаём QGridLayout
        central_widget.setLayout(grid_layout)  # Устанавливаем данное размещение в центральный виджет
        self.table = QTableView(self)
        self.table.setGeometry(30, 30, 580, 660)
        self.model = QtGui.QStandardItemModel(5, 3, self)
        self.game = Game(5,9)
        for i in range(self.game.height):
            for j in range(self.game.width):
                self.model.setItem(i, j, QtGui.QStandardItem())
                color = self.define_color(self.game.matrix[i][j])
                self.model.item(i, j).setBackground(color)
        self.table.setModel(self.model)
        grid_layout.addWidget(selectBtn, 0, 0)
        grid_layout.addWidget(restartBtn,1,0)
        grid_layout.addWidget(self.table, 0, 1)  # Добавляем таблицу в сетку

        def new_mouse_press_event(e: QMouseEvent) -> None:
            idx = self.table.indexAt(e.pos())
            self.on_item_clicked(idx, e)
        self.table.mousePressEvent = new_mouse_press_event


    def init_game_field(self):
        self.game = Game(5,9)
        for i in range(self.game.height):
            for j in range(self.game.width):
                self.table.setItem(i, j, QTableWidgetItem())
                color = self.define_color(self.game.matrix[i][j])
                self.table.item(i, j).setBackground(color)

    def define_color(self, color):
        if color == Color.BLUE:
            return QtGui.QColor(0,0,255)
        if color == Color.GREEN:
            return QtGui.QColor(0,255,0)
        if color == Color.RED:
            return QtGui.QColor(255,0,0)
        if color == Color.PRINCE:
            return QtGui.QColor(205,205,205)
        if color == Color.PRINCESS:
            return QtGui.QColor(235,155,235)

    def on_item_clicked(self, e: QModelIndex, me: QMouseEvent = None) -> None:
        if me.button() == Qt.LeftButton:
            self.left_mouse_click(e.row(), e.column())


    def left_mouse_click(self, row, col) -> None:
        if self.previousClick == 0:
            self.previousClick = [int(row), int(col)]
            #self.table.item(row, col).setFocusPolicy(Qt.NoFocus)
        else:
            if math.fabs(self.previousClick[0] - int(row)) + math.fabs(self.previousClick[1] - int(col)) != 1:
                self.selected = []
                raise Exception("Последовательность выделена неверна")
        self.selected.append([row, col])
        self.previousClick = [int(row), int(col)]