Exemple #1
0
class SongsTable_Container(FFrame):
    def __init__(self, app, parent=None):
        super().__init__(parent)
        self._app = app

        self.songs_table = None
        self.table_control = TableControl(self._app)
        self._layout = QVBoxLayout(self)
        self.setup_ui()

    def setup_ui(self):
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)

        self._layout.addWidget(self.table_control)

    def set_table(self, songs_table):
        if self.songs_table:
            self._layout.replaceWidget(self.songs_table, songs_table)
            self.songs_table.close()
            del self.songs_table
        else:
            self._layout.addWidget(songs_table)
            self._layout.addSpacing(10)
        self.songs_table = songs_table
Exemple #2
0
class PlotWindow(QWidget):
    def __init__(self, data):
        super().__init__()
        self.plot_tabs(data)
        self.setWindowTitle('Pipeline results')
        self.show()

    def widget(self, y, x=None, labels={'left': '', 'bottom': ''}):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        pw = pg.PlotWidget(pen=None, labels=labels)

        pw.plot(x=x, y=y, symbol='o', symbolSize=5, pen=None)
        return pw

    def plot_tabs(self, data):
        import numpy as np
        layout = QVBoxLayout()
        self.setLayout(layout)

        tabs = QTabWidget()
        layout.addWidget(tabs)
        ''' Optimization tab '''
        plot_data = data['Optimization']
        tab_widget = self.widget(x=plot_data['x'],
                                 y=plot_data['y'],
                                 labels=plot_data['labels'])
        tabs.addTab(tab_widget, 'Optimization')
        ''' Cost vs parameter tab '''
        tab_widget = QWidget()
        self.tab_layout = QVBoxLayout()
        tab_widget.setLayout(self.tab_layout)
        tabs.addTab(tab_widget, '1D')

        box = QComboBox()
        box.currentTextChanged.connect(self.plot_axis)
        pipe_data = data['Data']
        self.points = np.atleast_2d(data['Data']['points'])
        self.costs = np.array(data['Data']['costs'])
        self.axis_widget = self.widget(x=self.points[:, 0], y=self.costs)

        self.tab_layout.addWidget(box)
        for item in range(self.points.shape[1]):
            box.addItem(str(item))
        self.tab_layout.addWidget(self.axis_widget)

    def plot_axis(self, axis):
        axis = int(axis)
        new_widget = self.widget(x=self.points[:, axis],
                                 y=self.costs,
                                 labels={
                                     'bottom': str(axis),
                                     'left': 'Result'
                                 })
        self.tab_layout.replaceWidget(self.axis_widget, new_widget)
        self.axis_widget = new_widget
Exemple #3
0
class MyApp(env, QMainWindow, Ui_MainWindow,):

    def __init__(self):
        self.env = env        
        QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        super().__init__()



        self.initUI()
        self.initBtn()
        self.initFrame()

    def initFrame(self):
        self.main_widget = self.frame
        self.layout = QVBoxLayout(self.main_widget)
        self.f = MyMplCanvas(self.main_widget)
        self.layout.addWidget(self.f)

    def initUI(self):               

        self.setupUi(self)
        self.setWindowTitle("PyQt5结合Matplotlib绘图")
        self.setWindowIcon(QIcon("rocket.ico"))   # 设置图标,linux下只有任务栏会显示图标

        self.show()

    def initBtn(self):
        self.btnPlot.clicked.connect(self.plotButton_callback)
        self.btnPlot.setToolTip("Button")         

    def plotButton_callback(self):

        self.drawFrame()

    def drawFrame(self):

        dc = MyDynamicMplCanvas(self.env, self.f, width=5, height=4, dpi=100)
        self.layout.replaceWidget(self.f,dc) # 替换控件
Exemple #4
0
class SongsTableContainer(MFrame):
    def __init__(self, app, parent=None):
        super().__init__(parent)
        self._app = app

        self.songs_table = None
        self.table_control = TableControl(self._app)
        self._layout = QVBoxLayout(self)
        self.setup_ui()

    def set_table(self, songs_table):
        if self.songs_table:
            self._layout.replaceWidget(self.songs_table, songs_table)
            self.songs_table.deleteLater()
        else:
            self._layout.addWidget(songs_table)
            self._layout.addSpacing(10)
        self.songs_table = songs_table

    def setup_ui(self):
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)
        self._layout.addWidget(self.table_control)
Exemple #5
0
class PageEditor(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.placeholder = QWidget()
        hbox = QHBoxLayout()
        hbox.setAlignment(Qt.AlignLeft)
        hbox.setSpacing(10)
        addSection = HyperLink("(+) Add Section")
        addFullSection = HyperLink("(+) Add Full Width Section")
        l = QVBoxLayout()
        self.layout = QVBoxLayout()
        l.addLayout(self.layout)
        l.addWidget(self.placeholder)
        hbox.addWidget(addSection)
        hbox.addWidget(addFullSection)
        self.layout.addLayout(hbox)
        self.layout.addStretch()
        self.setLayout(l)
        self.setAcceptDrops(True)
        addSection.clicked.connect(self.addNormalSection)
        addFullSection.clicked.connect(self.addFullSection)

    def enableColumnAcceptDrop(self, mode):
        for i in range(self.layout.count()):
            ce = self.layout.itemAt(i).widget()
            if isinstance(ce, ColumnEditor):
                ce.enableColumnAcceptDrop(mode)

    def enableSectionAcceptDrop(self, mode):
        for i in range(self.layout.count()):
            se = self.layout.itemAt(i).widget()
            if isinstance(se, SectionEditor):
                se.enableColumnAcceptDrop(mode)

    def addFullSection(self):
        se = SectionEditor(True)
        self.addSection(se)
        ce = self.getContentEditor()
        if ce:
            sec = Section()
            sec.fullwidth = True
            se.load(sec)
            ce.content.appendSection(sec)
            ce.editChanged("Add Section")

    def addNormalSection(self):
        se = SectionEditor(False)
        self.addSection(se)
        ce = self.getContentEditor()
        if ce:
            sec = Section()
            sec.fullwidth = False
            se.load(sec)
            ce.content.appendSection(sec)
            ce.editChanged("Add Section")

    def addSection(self, se):
        se.sectionEditorCopied.connect(self.copySection)
        self.layout.insertWidget(self.layout.count() - 2, se)

    def sections(self):
        list = []
        for i in range(self.layout.count()):
            se = self.layout.itemAt(i).widget()
            if isinstance(se, SectionEditor):
                list.append(se)
        return list

    def removeSectionEditor(self, se):
        self.layout.removeWidget(se)

    def removeSection(self, se):
        sec = se.section
        se.hide()
        self.layout.removeWidget(se)
        del se
        ce = self.getContentEditor()
        if ce:
            ce.content.removeSection(sec)
            ce.editChanged("Delete Section")

    def copySection(self, se):
        see = SectionEditor(se.fullwidth)
        self.addSection(see)
        ce = self.getContentEditor()
        if ce:
            sec = se.section.clone()
            see.load(sec)
            ce.content.appendSection(sec)
            ce.editChanged("Copy Section")

    def getContentEditor(self):
        sa = self.parentWidget()
        if sa:
            vp = sa.parentWidget()
            if vp:
                cee = vp.parentWidget()
                if cee:
                    return cee
        return None

    def dragEnterEvent(self, event):
        myData = event.mimeData()
        if myData:
            se = myData.getData()
            if isinstance(se, SectionEditor):
                # insert a dropzone at the end
                self.layout.addWidget(DropZone(myData.width, myData.height))
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def dragLeaveEvent(self, event):
        # remove dropzones
        for i in range(self.layout.count()):
            dz = self.layout.itemAt(i).widget()
            if isinstance(dz, DropZone):
                dz.hide()
                self.layout.removeWidget(dz)
                del dz
                break
        event.accept()

    def dragMoveEvent(self, event):
        myData = event.mimeData()
        if myData:
            se = myData.getData()
            if isinstance(se, SectionEditor):
                height = 0
                row = 0

                # evaluate position for the dropzone to be placed
                for i in range(self.layout.count()):
                    editor = self.layout.itemAt(i).widget()
                    if isinstance(editor, SectionEditor):
                        if event.pos().y() > height and event.pos().y(
                        ) < height + editor.height():
                            break
                        height += editor.height()
                        row = row + 1

                # find dropzone and replace it to new location
                for i in range(self.layout.count()):
                    dz = self.layout.itemAt(i).widget()
                    if isinstance(dz, DropZone):
                        if i != row:
                            self.layout.insertWidget(row, dz)
                        break
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def dropEvent(self, event):
        myData = event.mimeData()
        if myData:
            se = myData.getData()
            if isinstance(se, SectionEditor):
                # place the dragged SectionEditor to the place where DropZone is now
                for i in range(self.layout.count()):
                    dz = self.layout.itemAt(i).widget()
                    if isinstance(dz, DropZone):
                        dz.hide()
                        self.layout.replaceWidget(dz, se)
                        new_pos = i
                        se.show()
                        del dz
                        break
                ce = self.getContentEditor()
                if ce:
                    ce.content.changeSectionPos(se.section, new_pos)
                    ce.editChanged("Move Section")
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()
Exemple #6
0
class PyTouchCubeGUI(QMainWindow):

    item_selected = None
    props_current = None
    printer_select = None
    save_printable_button = None

    def __init__(self, app: QApplication):
        super().__init__()

        Settings.load()

        self.setWindowTitle(APP_NAME)

        self.app = app
        app.setApplicationName(APP_NAME)
        app.setApplicationDisplayName(APP_NAME)

        self.preview_image = QLabel('No items to preview')
        self.preview_image.setFixedHeight(USABLE_HEIGHT)

        self.props_empty = False

        self.save_image_button = QPushButton('Save image')
        self.save_image_button.setDisabled(True)

        self.tree_view = ItemView()
        self.items = self.create_model()
        self.item_data = []
        self.tree_view.setRootIsDecorated(False)
        # self.tree_view.setAlternatingRowColors(True)
        self.tree_view.setModel(self.items)
        self.tree_view.clicked.connect(self.tree_view_clicked)
        self.tree_view.rowMoved.connect(self.tree_view_reorder)
        self.tree_view.setDragEnabled(True)
        self.tree_view.setDragDropMode(QTreeView.InternalMove)
        self.tree_view.setItemsExpandable(False)
        self.tree_view.setDragDropOverwriteMode(False)

        root = QVBoxLayout()

        items_layout = QHBoxLayout()

        group = QGroupBox('Source items:')
        layout = QVBoxLayout()
        layout.addWidget(self.tree_view)
        buttons = QHBoxLayout()

        add_menu = QMenu()
        add_menu.addAction(Text.get_add_add_action(self))
        add_menu.addAction(Image.get_add_add_action(self))
        add_menu.addAction(Barcode.get_add_add_action(self))
        add_menu.addAction(QrCode.get_add_add_action(self))

        add_menu.addSeparator()
        add_menu.addAction(Spacing.get_add_add_action(self))

        add_button = QPushButton('Add')
        add_button.setMenu(add_menu)
        buttons.addWidget(add_button)

        #buttons.addWidget(add_text_button)
        #buttons.addWidget(add_barcode_button)
        buttons.addStretch()
        buttons.setSpacing(1)

        b_down = QPushButton('⬇︎')
        b_down.clicked.connect(lambda _: self.move_item(1))
        b_up = QPushButton('⬆︎')
        b_up.clicked.connect(lambda _: self.move_item(-1))
        b_delete = QPushButton('Delete')
        b_delete.clicked.connect(self.delete_item)

        b_clone = QPushButton('Copy')
        b_clone.clicked.connect(self.on_clone)

        buttons.addWidget(b_clone)
        buttons.addSpacing(10)
        buttons.addWidget(b_up)
        buttons.addWidget(b_down)
        buttons.addSpacing(10)
        buttons.addWidget(b_delete)

        layout.addLayout(buttons)
        group.setLayout(layout)
        items_layout.addWidget(group)

        self.property_group = QGroupBox('Item properties:')
        self.props_layout = QVBoxLayout()

        self.property_group.setLayout(self.props_layout)

        self.props_current = QLabel()
        self.props_layout.addWidget(self.props_current)
        self.save_printable_button = QPushButton('Save Changes')
        self.save_printable_button.clicked.connect(self.save_props)
        self.props_layout.addWidget(self.save_printable_button)
        self.update_props()

        items_layout.addWidget(self.property_group)

        root.addLayout(items_layout)

        group = QGroupBox('Preview:')
        layout = QVBoxLayout()

        preview_wrapper = QScrollArea(self)

        #prev_layout = QHBoxLayout()
        preview_wrapper.setWidget(self.preview_image)
        preview_wrapper.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        preview_wrapper.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        preview_wrapper.setWidgetResizable(True)
        preview_wrapper.setFixedHeight(USABLE_HEIGHT)
        layout.addWidget(preview_wrapper)

        # layout.addWidget(self.save_image_button)
        group.setLayout(layout)
        group.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))

        root.addWidget(group)

        self.printer_select = QComboBox(self)
        fs_model = QFileSystemModel(self)
        #model_proxy = QSortFilterProxyModel(self)
        #model_proxy.setSourceModel(fs_model)
        # fs_model.setNameFilters(['tty.PT-P3*'])

        potential_printer = None
        printers = QStandardItemModel()

        #for p in QDir('/dev').entryList(['tty*'], QDir.System, QDir.Name):
        #    if p.startswith('tty.'):
        for p in LabelMaker.list_serial_ports():
            # pprint(p.__dict__)
            item = [QStandardItem(p.name), QStandardItem(p.device)]
            print(p.name)
            printers.appendRow(item)
            '''
            item = QStandardItem('/dev/' + p)
            printers.appendRow(item)
            if p.startswith('tty.PT-P3'):
                potential_printer = item
            '''

        #print(printers.entryList())

        #model_proxy.setRecursiveFilteringEnabled(True)
        #model_proxy.setFilterKeyColumn(0)

        fs_model.setRootPath('/dev/')  #/Users/nilsmasen')
        fs_model.setFilter(QDir.System)

        dev_index = fs_model.index('/dev')
        #proxy_dev = model_proxy.mapFromSource(dev_index)

        self.printer_select.setModel(printers)

        if potential_printer is not None:
            index = printers.indexFromItem(potential_printer)
            self.printer_select.setCurrentIndex(index.row())
        #printer_select.setRootModelIndex(dev_index)
        #printer_select.setRootIndex(dev_index)
        #printer_select.setExpanded(dev_index, True)
        #model_proxy.setFilterWildcard('tty*')

        bottom_box = QGroupBox('Print label: ')
        bottom_bar = QHBoxLayout()
        bottom_bar.addWidget(QLabel('Print device:'))
        bottom_bar.addWidget(self.printer_select)
        bottom_bar.addStretch()
        # /dev/tty.PT-P300BT0607-Serial
        print_button = QPushButton('Print')
        print_button.setFixedWidth(100)
        bottom_bar.addWidget(print_button)
        print_button.clicked.connect(self.print_clicked)

        bottom_box.setLayout(bottom_bar)
        root.addWidget(bottom_box)

        root_widget = QWidget()
        root_widget.setFixedWidth(800)
        root_widget.setLayout(root)
        self.setCentralWidget(root_widget)
        menu = QMenuBar()
        self.setMenuBar(menu)

        menu.setWindowTitle(APP_NAME)
        tools_menu = menu.addMenu('Python')
        prefs = QAction('&Preferences', self)
        prefs.triggered.connect(self.on_prefs)
        tools_menu.addAction(prefs)
        about = QAction('About ' + APP_NAME, self)
        about.triggered.connect(self.on_prefs)
        about.setMenuRole(QAction.AboutRole)
        tools_menu.addAction(about)

        file_menu = menu.addMenu('Label')
        act_new = QAction('&New', self)
        act_new.triggered.connect(self.on_new)
        file_menu.addAction(act_new)
        file_menu.addSeparator()
        act_open = QAction('&Open', self)
        act_open.triggered.connect(self.on_open)
        act_open.setShortcut(QKeySequence('Ctrl+O'))
        file_menu.addAction(act_open)
        file_menu.addSeparator()
        act_save = QAction('&Save', self)
        act_save.triggered.connect(self.on_save)
        act_save.setShortcut(QKeySequence("Ctrl+S"))
        file_menu.addAction(act_save)
        act_save_as = QAction('Save &as...', self)
        act_save_as.triggered.connect(self.on_save_as)
        act_save_as.setShortcut(QKeySequence("Ctrl+Shift+S"))
        file_menu.addAction(act_save_as)
        file_menu.addSeparator()
        file_menu.addAction(QAction('&Export image', self))

        # menu.setNativeMenuBar(False)

    def on_new(self):
        self.item_data = []
        self.items.clear()
        self.update_items()
        self.update_preview()

    def on_prefs(self):
        QMessageBox.information(
            self, "Info",
            "{0} v{1}\n\nhttps://github.com/piksel/pytouch-cube".format(
                APP_NAME, APP_VERSION))

    def run(self):

        self.show()
        #self.add_item(Text(TextData('foo')))
        #self.add_item(Text(TextData('Bar1')))
        #self.add_item(Text(TextData('Bar2')))
        #self.add_item(Spacing(SpacingData(10)))
        #self.add_item(Text(TextData('baz')))
        # self.add_item(Barcode(BarcodeData('123456789012')))
        # self.add_item(Barcode(BarcodeData('ACE222', 'code128')))

        self.app.exec_()

    def on_save(self):
        if self.current_file is None:
            self.on_save_as()
        else:
            self.save()

    def on_save_as(self):
        user_home = os.path.expanduser('~')
        save_initial_path = os.path.join(user_home, 'Documents')
        if not os.path.isdir(save_initial_path):
            save_initial_path = user_home
        file_path, format = QFileDialog.getSaveFileName(
            self,
            caption='Save Label',
            directory=save_initial_path,
            filter='Label Files (*.p3label)')

        if len(file_path) <= 0:
            return

        self.current_file = file_path
        self.save()

    def on_open(self):
        user_home = os.path.expanduser('~')
        open_initial_path = os.path.join(user_home, 'Documents')
        if not os.path.isdir(open_initial_path):
            open_initial_path = user_home
        file_path, format = QFileDialog.getOpenFileName(
            self,
            caption='Open Label',
            directory=open_initial_path,
            filter='Label Files (*.p3label)')

        if len(file_path) <= 0:
            return

        self.current_file = file_path
        self.open()

    def save(self):
        with open(self.current_file, 'wb') as file:
            pickler = pickle.Pickler(file)
            pickler.dump(self.item_data)

    def open(self):
        with open(self.current_file, 'rb') as file:
            unpickler = pickle.Unpickler(file)
            self.item_data = unpickler.load()
            self.update_items()
            self.update_preview()

    def print_clicked(self):

        log_console = QTextEdit(self)
        log_console.setReadOnly(True)
        font = QFont('Fira')
        font.setStyleHint(QFont.Monospace, QFont.PreferDefault)
        font.setFamilies([
            'Fira', 'Source Code Pro', 'Monaco', 'Consolas', 'Monospaced',
            'Courier'
        ])
        log_console.setFont(font)
        modal = QDialog(self)
        modal_layout = QVBoxLayout(self)
        modal_layout.addWidget(log_console)

        close = QPushButton('close')
        close.setDisabled(True)
        close.clicked.connect(lambda _: modal.close())
        modal_layout.addWidget(close)

        modal.setLayout(modal_layout)
        modal.setFixedWidth(self.width() * .9)
        modal.setFixedHeight(self.height() * .9)
        modal.open()

        def fmt_log(message):
            now = datetime.datetime.now()
            return '{0} {1}'.format(now.isoformat(), message)

        def log(message):
            log_console.insertPlainText('\n' + fmt_log(message))
            log_console.ensureCursorVisible()

        def done(exception):
            if exception is not None:
                log('Failed to print due to the following error:\n')
                log_console.insertHtml(
                    '<pre style="color:red">{0}</pre>'.format(exception))
            else:
                log('Printing completed without any errors!\n')
            close.setDisabled(False)

        log_console.insertPlainText(fmt_log('Starting print thread...'))

        print_device = self.printer_select.currentText()
        self.print_thread = PrintThread(QImage(self.print_image), print_device)
        self.print_thread.log.connect(log)
        self.print_thread.done.connect(done)

        self.print_thread.start()

    def tree_view_clicked(self, index):
        self.item_selected = index.row()
        self.update_props()

    def move_item(self, direction):

        current = self.tree_view.currentIndex()
        print(direction, current)
        if not current.isValid() or current.row() < 0:
            print('invalid index', current.row())
            self.tree_view.repaint()
            return
        old = current.row()
        new = current.row() + direction
        if new < 0 or new >= self.items.rowCount():
            print('cannot move from', old, 'to', new)
            return
        # self.items.moveRow(current.parent(), old, current.parent(), new)
        self.tree_view_reorder(old, new)
        self.update_items()

        self.tree_view.setCurrentIndex(current.sibling(new, 0))
        self.tree_view.repaint()

    def delete_item(self):
        current = self.tree_view.currentIndex()
        if not current.isValid() or current.row() < 0:
            return
        self.item_data.remove(self.item_data[current.row()])

        self.items.removeRow(current.row())
        self.update_items()
        self.update_preview()

    def on_clone(self):
        current = self.tree_view.currentIndex()
        if not current.isValid() or current.row() < 0:
            return

        original = self.item_data[current.row()]
        copy = original.__class__(original.data.clone())
        new_index = current.row() + 1
        self.item_data.insert(new_index, copy)

        self.update_items()
        self.update_preview()

        self.tree_view.setCurrentIndex(self.items.index(new_index, 0))
        self.tree_view.repaint()

        self.item_selected = new_index
        self.update_props()

    def tree_view_reorder(self, old, new):
        item = self.item_data.pop(old)
        self.item_data.insert(new, item)
        self.update_preview()
        print(old, '=>', new)
        return item

    def create_model(self):
        model = QStandardItemModel(0, 2, self)
        model.setHeaderData(ModelCol.TYPE.value, Qt.Horizontal, 'Type')
        model.setHeaderData(ModelCol.DATA.value, Qt.Horizontal, 'Data')
        return model

    def add_item(self, item: Printable):
        current = self.tree_view.currentIndex()
        row = self.items.rowCount()
        if current.isValid():
            row = current.row()
        self.items.insertRow(row, item.get_list_item())
        self.item_data.insert(row, item)
        if current.isValid():
            self.tree_view.setCurrentIndex(current)
        else:
            self.tree_view.setCurrentIndex(self.items.createIndex(row, 0))
        self.item_selected = row
        self.update_preview()
        self.update_props()

    def save_props(self):
        if isinstance(self.props_current, PropsEdit):
            self.props_current.save()
            current = self.tree_view.currentIndex()
            self.update_items()
            self.tree_view.setCurrentIndex(current)

    def update_items(self, keep_index=False):
        current = self.tree_view.currentIndex()
        for row in range(0, len(self.item_data)):
            item = self.item_data[row].get_list_item()
            for col in range(0, len(item)):
                self.items.setItem(row, col, item[col])

        if keep_index:
            self.tree_view.setCurrentIndex(current)

    def update_preview(self):
        item_renders = []
        width_needed = 0

        for i in range(0, len(self.item_data)):
            render = self.item_data[i].render()
            render_error = self.item_data[i].get_render_error()
            if render_error is not None:
                QMessageBox.warning(
                    self, 'Failed to render item',
                    'Failed to render item:\n' + str(render_error))
            item_renders.append(render)
            width_needed += render.width()

        x = 0
        image = QImage(width_needed, USABLE_HEIGHT, QImage.Format_Mono)
        image.fill(QColor(255, 255, 255))
        painter = QPainter(image)
        for render in iter(item_renders):
            painter.drawImage(x, 0, render)
            x += render.width()
        painter.end()
        del painter

        self.print_image = image
        self.preview_image.setPixmap(QPixmap.fromImage(image))
        self.preview_image.repaint()

    def update_props(self):

        if self.item_selected is None:
            if self.props_empty:
                return
            new_widget = make_props_empty(self)
            if self.save_printable_button is not None:
                self.save_printable_button.setEnabled(False)
            self.props_empty = True
        else:
            item: Printable = self.item_data[self.item_selected]
            new_widget = item.get_props_editor(self)
            self.save_printable_button.setEnabled(True)

        self.props_layout.replaceWidget(self.props_current, new_widget)
        self.props_current.close()
        self.props_current = new_widget
class MainPanel(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Weight Loss"
        self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }
    QComboBox{
      border-radius: 4px;
      font-size: 18px;
      font-weight: bold;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
      min-height: 28px;
      background-color: #440D0F;
    }
    QComboBox:down-arrow{
      width: 0px;
      height: 0px;
      background: #d3d3d3; 
      opacity:0
    }
    QComboBox:drop-down{
      background-color: #440D0F;
      border: 0px;
      opacity:0;
      border-radius: 0px;
      width: 0px;
      height: 0px;
    }
    QComboBox:hover:!pressed{
      background-color: #5D1A1D;
    }
    QComboBox:pressed{
      background-color: #551812;
    }
    """)

        self.db_wrapper.create_local_table(self.table_name)
        self.db_wrapper.create_local_table("Nutrition")

        if self.db_wrapper.local_table_is_empty("Nutrition"):
            self.db_wrapper.insert_default_values("Nutrition")

        if self.db_wrapper.local_table_is_empty(self.table_name):
            self.db_wrapper.insert_default_values(self.table_name)

        self.fetch_user_data()
        self.date = datetime.today().strftime("%d/%m/%Y")
        self.current_year = datetime.today().year
        self.calorie_goal = self.db_wrapper.fetch_local_column(
            "Nutrition", "calorie_goal")

        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        weight_loss_units = "kg" if self.db_wrapper.fetch_local_column(
            self.table_name, "units") == "metric" else "lb"
        self.weight_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "weight_history"))

        if self.units != weight_loss_units:
            units_name = "metric" if self.units == "kg" else "imperial"
            self.db_wrapper.update_table_column(self.table_name, "units",
                                                units_name)
            if units_name == "metric":
                for date in self.weight_history:
                    self.weight_history[date] = str(
                        pounds_to_kg(self.weight_history[date]))

            elif units_name == "imperial":
                for date in self.weight_history:
                    self.weight_history[date] = str(
                        kg_to_pounds(self.weight_history[date]))

            self.db_wrapper.update_table_column(
                self.table_name, "weight_history",
                json.dumps(self.weight_history))

        self.preferred_activity = self.db_wrapper.fetch_local_column(
            self.table_name, "preferred_activity")
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        if not self.date in self.cardio_history:
            self.add_date_to_cardio_history()
        if not self.date in self.weight_history:
            self.add_date_to_weight_history()

        self.init_cardio_labels()
        self.create_panel()

    def create_panel(self):
        grid = QGridLayout()
        grid.addLayout(self.create_description(), 0, 0, 1, 1)
        grid.addWidget(self.create_graph(), 1, 0, 4, 1)
        grid.addLayout(self.create_bottom_layout(), 5, 0, 3, 1)
        self.setLayout(grid)

    def create_description(self):
        description = QVBoxLayout()
        description_font = QFont("Montserrat", 12)
        description_label = QLabel(
            "Keep notes and track your weight loss journey.", self)
        description_label.setFont(description_font)
        description_label.setFixedHeight(20)
        description.addWidget(description_label)
        return description

    def create_graph(self):
        self.graph_layout = QVBoxLayout()

        graph = WeightLossGraphCanvas(
            self.db_wrapper.months[datetime.today().month - 1],
            self.current_year, self)
        toolbar = NavigationToolbar(graph, self)
        toolbar.setStyleSheet("background-color: white;")

        combobox_layout = QHBoxLayout()
        self.months_combobox = QComboBox()

        months = []
        for entry in self.weight_history:
            month = entry.split("/")[1]
            for month_name, code in self.db_wrapper.months_mappings.items():
                if code == month: month = month_name
            if not month in months:
                months.append(month)
        if len(months) == 0:
            months.append(self.db_wrapper.months[datetime.today().month - 1])
        self.months_combobox.addItems(months)
        self.months_combobox.setCurrentText(
            self.db_wrapper.months[datetime.today().month - 1])
        self.months_combobox.currentTextChanged.connect(
            lambda month: self.change_month_graph(month))

        self.change_year_combobox = QComboBox()

        years = []
        for entry in self.weight_history:
            if not entry.split("/")[-1] in years:
                years.append(entry.split("/")[-1])
        if len(years) == 0: years.append(str(self.current_year))
        self.change_year_combobox.addItems(list(reversed(years)))
        self.change_year_combobox.currentTextChanged.connect(
            lambda year: self.change_year_graph(year))

        combobox_layout.addWidget(self.months_combobox)
        combobox_layout.addWidget(self.change_year_combobox)

        self.graph_layout.addWidget(toolbar)
        self.graph_layout.addWidget(graph)
        self.graph_layout.addLayout(combobox_layout)

        framed_graph = QFrame(self)
        framed_graph.setFrameStyle(QFrame.Box)
        framed_graph.setLineWidth(3)
        framed_graph.setLayout(self.graph_layout)

        return framed_graph

    def create_bottom_layout(self):
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.create_weight_loss())
        bottom_layout.addWidget(self.create_cardio_notes())
        return bottom_layout

    def create_weight_loss(self):
        weight_loss = QVBoxLayout()
        main_label = QLabel("Weight Loss")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        current_weight_layout = QHBoxLayout()
        self.current_weight_label = QLabel(" ".join(
            ["Current Weight:", self.current_weight, self.units]))
        update_current_weight_button = QPushButton("Update")
        update_current_weight_button.clicked.connect(
            lambda: self.update_value("Current Weight", self.current_weight))
        current_weight_layout.addWidget(self.current_weight_label)
        current_weight_layout.addWidget(update_current_weight_button)

        weight_goal_layout = QHBoxLayout()
        self.weight_goal_label = QLabel(" ".join(
            ["Weight Goal:", self.goal_weight, self.units]))
        update_weight_goal_label = QPushButton("Update")
        update_weight_goal_label.clicked.connect(
            lambda: self.update_value("Weight Goal", self.goal_weight))
        weight_goal_layout.addWidget(self.weight_goal_label)
        weight_goal_layout.addWidget(update_weight_goal_label)

        loss_per_week_layout = QHBoxLayout()
        self.loss_per_week_label = QLabel(" ".join(
            ["Loss Per Week:",
             str(self.loss_per_week), self.units]))
        update_loss_per_week_label = QPushButton("Update")
        update_loss_per_week_label.clicked.connect(
            lambda: self.update_value("Loss Per Week", self.loss_per_week))
        loss_per_week_layout.addWidget(self.loss_per_week_label)
        loss_per_week_layout.addWidget(update_loss_per_week_label)

        calorie_intake_layout = QHBoxLayout()
        calorie_intake_label = QLabel(" ".join(
            ["Calorie Intake:",
             str(self.calorie_goal), "kcal"]))
        calorie_intake_layout.addWidget(calorie_intake_label)

        history_layout = QHBoxLayout()
        weight_loss_history_button = QPushButton("History")
        weight_loss_history_button.clicked.connect(
            lambda: self.show_weight_history())
        history_layout.addWidget(weight_loss_history_button)

        weight_loss.addWidget(main_label)
        weight_loss.addLayout(calorie_intake_layout)
        weight_loss.addLayout(current_weight_layout)
        weight_loss.addLayout(weight_goal_layout)
        weight_loss.addLayout(loss_per_week_layout)
        weight_loss.addLayout(history_layout)

        weight_loss.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")

        framed_layout.setLayout(weight_loss)

        return framed_layout

    def create_cardio_notes(self):
        cardio_notes = QVBoxLayout()
        main_label = QLabel("Cardio Notes")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        preferred_activity_layout = QHBoxLayout()
        self.preferred_activity_label = QLabel(" ".join(
            ["Preferred Activity:", self.preferred_activity]))
        self.preferred_activity_dropdown = QComboBox()
        self.preferred_activity_dropdown.addItems(
            ["Running", "Walking", "Cycling", "Swimming"])
        self.preferred_activity_dropdown.setCurrentText(
            self.preferred_activity)
        self.preferred_activity_dropdown.currentTextChanged.connect(
            lambda activity: self.set_new_preferred_activity(activity))

        preferred_activity_layout.addWidget(self.preferred_activity_label)
        preferred_activity_layout.addWidget(self.preferred_activity_dropdown)

        time_spent_layout = QHBoxLayout()
        self.time_spent_label = QLabel(" ".join(
            ["Time Spent:", self.time_spent, "min"]))
        update_time_spent_label = QPushButton("Update")
        update_time_spent_label.clicked.connect(
            lambda: self.update_value("Time Spent", self.time_spent))
        time_spent_layout.addWidget(self.time_spent_label)
        time_spent_layout.addWidget(update_time_spent_label)

        calories_burnt_layout = QHBoxLayout()
        self.calories_burnt_label = QLabel(" ".join(
            ["Calories Burnt:", self.calories_burnt, "kcal"]))
        update_calories_burnt_label = QPushButton("Update")
        update_calories_burnt_label.clicked.connect(
            lambda: self.update_value("Calories Burnt", self.calories_burnt))
        calories_burnt_layout.addWidget(self.calories_burnt_label)
        calories_burnt_layout.addWidget(update_calories_burnt_label)

        distance_travelled_layout = QHBoxLayout()
        self.distance_travelled_label = QLabel(" ".join(
            ["Distance Travelled:", self.distance_travelled, "m"]))
        update_distance_travelled_label = QPushButton("Update")
        update_distance_travelled_label.clicked.connect(
            lambda: self.update_value("Distance Travelled", self.
                                      distance_travelled))
        distance_travelled_layout.addWidget(self.distance_travelled_label)
        distance_travelled_layout.addWidget(update_distance_travelled_label)

        history_layout = QHBoxLayout()
        cardio_history_button = QPushButton("History")
        cardio_history_button.clicked.connect(
            lambda: self.show_cardio_history())
        self.save_changes_cardio_button = QPushButton("Save Changes")
        self.save_changes_cardio_button.clicked.connect(
            lambda: self.add_cardio_entry_to_cardio_history())
        history_layout.addWidget(cardio_history_button)
        history_layout.addWidget(self.save_changes_cardio_button)

        cardio_notes.addWidget(main_label)
        cardio_notes.addLayout(preferred_activity_layout)
        cardio_notes.addLayout(time_spent_layout)
        cardio_notes.addLayout(distance_travelled_layout)
        cardio_notes.addLayout(calories_burnt_layout)
        cardio_notes.addLayout(history_layout)

        cardio_notes.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")

        framed_layout.setLayout(cardio_notes)

        return framed_layout

    def update_value(self, to_edit, old_value):
        fitness_goal = None
        date = None
        if not to_edit == "Calories Burnt":
            if to_edit == "Loss Per Week":
                fitness_goal = self.user_data["Goal Params"][0]
            elif to_edit == "Current Weight":
                date = self.date
            self.dialog = WeightLossEditDialog(to_edit, old_value,
                                               fitness_goal, date)
            self.dialog.update_label_signal.connect(
                lambda label_to_update: self.update_weight_loss_label(
                    label_to_update))
            self.dialog.update_cardio_notes_signal.connect(
                lambda value_to_update: self.update_cardio_notes_label(
                    to_edit, value_to_update))
            self.dialog.update_graph_signal.connect(
                lambda signal: self.refresh_graph(signal))
        else:
            self.dialog = CaloriesBurntDialog(to_edit, old_value,
                                              self.time_spent,
                                              self.distance_travelled,
                                              self.preferred_activity,
                                              self.current_weight)
            self.dialog.update_calories_label_signal.connect(
                lambda value_to_update: self.update_cardio_notes_label(
                    to_edit, value_to_update))
        self.dialog.show()

    @pyqtSlot(bool)
    def update_weight_loss_label(self, signal):
        if signal:
            self.fetch_user_data()
            self.current_weight_label.setText(" ".join(
                ["Current Weight:",
                 str(self.current_weight), self.units]))
            self.weight_goal_label.setText(" ".join(
                ["Weight Goal:",
                 str(self.goal_weight), self.units]))
            self.loss_per_week_label.setText(" ".join(
                ["Loss Per Week:",
                 str(self.loss_per_week), self.units]))

    @pyqtSlot(str)
    def update_cardio_notes_label(self, to_edit, value_to_update):
        if to_edit == "Time Spent":
            self.time_spent = value_to_update
            self.time_spent_label.setText(" ".join(
                ["Time Spent:", str(value_to_update), "min"]))
        elif to_edit == "Distance Travelled":
            self.distance_travelled = value_to_update
            self.distance_travelled_label.setText(" ".join(
                ["Distance Travelled:",
                 str(value_to_update), "m"]))
        elif to_edit == "Calories Burnt":
            self.calories_burnt = value_to_update
            self.calories_burnt_label.setText(" ".join(
                ["Calories Burnt",
                 str(value_to_update), "kcal"]))

    def fetch_user_data(self):
        self.user_data = self.db_wrapper.fetch_local_user_info()
        self.current_weight = self.user_data["Weight"]
        self.goal_weight = self.user_data["Weight Goal"]
        self.loss_per_week = self.user_data["Goal Params"][1]

    def show_weight_history(self):
        self.history = WeightLossHistory()
        self.history.update_weight_loss_label_signal.connect(
            lambda signal: self.update_weight_loss_label(signal))
        self.history.setGeometry(100, 200, 300, 300)
        self.history.show()

    def show_cardio_history(self):
        self.cardio_history_dialog = CardioHistory()
        self.cardio_history_dialog.refresh_cardio_labels_signal.connect(
            lambda signal: self.refresh_cardio_notes(signal))
        self.cardio_history_dialog.setGeometry(100, 200, 300, 300)
        self.cardio_history_dialog.show()

    @pyqtSlot(bool)
    def refresh_cardio_notes(self, signal):
        if signal:
            self.cardio_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "cardio_history"))
            self.init_cardio_labels()
            self.time_spent_label.setText(" ".join(
                ["Time Spent:", self.time_spent, "min"]))
            self.distance_travelled_label.setText(" ".join(
                ["Distance Travelled:", self.distance_travelled, "m"]))
            self.calories_burnt_label.setText(" ".join(
                ["Calories Burnt:", self.calories_burnt, "kcal"]))

    def set_new_preferred_activity(self, activity):
        self.preferred_activity = activity
        self.preferred_activity_label.setText(" ".join(
            ["Preferred Activity:", activity]))
        self.preferred_activity_dropdown.setCurrentText(activity)
        self.db_wrapper.update_table_column(self.table_name,
                                            "preferred_activity",
                                            self.preferred_activity)
        self.init_cardio_labels()
        self.time_spent_label.setText(" ".join(
            ["Time Spent:", self.time_spent, "min"]))
        self.distance_travelled_label.setText(" ".join(
            ["Distance Travelled:", self.distance_travelled, "m"]))
        self.calories_burnt_label.setText(" ".join(
            ["Calories Burnt:", self.calories_burnt, "kcal"]))

    def init_cardio_labels(self):
        if len(self.cardio_history[self.date][self.preferred_activity]) > 0:
            self.today_exercise = self.cardio_history[self.date][
                self.preferred_activity][-1]
            self.time_spent = self.today_exercise["Time Spent"]
            self.distance_travelled = self.today_exercise["Distance Travelled"]
            self.calories_burnt = self.today_exercise["Calories Burnt"]
        else:
            self.time_spent = "0"
            self.distance_travelled = "0"
            self.calories_burnt = "0"

    def add_date_to_cardio_history(self):
        activities = ["Running", "Walking", "Cycling", "Swimming"]
        self.cardio_history[self.date] = {}
        for activity in activities:
            self.cardio_history[self.date][activity] = []

        cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            cardio_history)

    def add_cardio_entry_to_cardio_history(self):
        date = datetime.today().strftime("%d/%m/%Y")
        new_entry = {
            "Time Spent": str(self.time_spent),
            "Distance Travelled": str(self.distance_travelled),
            "Calories Burnt": str(self.calories_burnt)
        }
        self.cardio_history[date][self.preferred_activity].append(new_entry)
        current_cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            current_cardio_history)

    def add_date_to_weight_history(self):
        try:
            last_entry = list(self.weight_history.values())[-1]
            self.weight_history[self.date] = last_entry
            self.db_wrapper.update_table_column(
                self.table_name, "weight_history",
                json.dumps(self.weight_history))
        except IndexError:  # no records
            pass

    @pyqtSlot(bool)
    def refresh_graph(self, signal):
        if signal:
            self.weight_history = self.db_wrapper.fetch_local_column(
                self.table_name, "weight_history")
            self.replace_graph(str(self.months_combobox.currentText()))

    def replace_graph(self, month):
        new_graph = WeightLossGraphCanvas(month, self.current_year, self)
        new_toolbar = NavigationToolbar(new_graph, self)

        old_toolbar_reference = self.graph_layout.itemAt(0).widget()
        old_graph_reference = self.graph_layout.itemAt(1).widget()

        self.graph_layout.replaceWidget(old_toolbar_reference, new_toolbar)
        self.graph_layout.replaceWidget(old_graph_reference, new_graph)

    def change_year_graph(self, year):
        self.current_year = year
        self.replace_graph(str(self.months_combobox.currentText()))

    def change_month_graph(self, month):
        self.replace_graph(str(month))
Exemple #8
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # Stores all images inside the current image's directory.
        self.dirImages = []

        # Store the current image being displayed.
        self.currentImage = None

        self.setupMenuBar()
        self.setupUi()

    def setupUi(self):
        """
        Setup the application UI.
        """
        self.resize(QGuiApplication.primaryScreen().availableSize() * 2 / 3)

        # Instanciate the image viewer.
        self.imageView = ImageView()

        # Get the system font size
        font = QFont()
        size = font.pointSize()

        # Increase size.
        font.setPointSize(size + 2)

        # Create a label to display the images.
        self.introLabel = QLabel("Press Ctrl+O to select an image"
                                 "\nOr choose a directory by pressing Ctrl+D")
        self.introLabel.setAlignment(Qt.AlignCenter)
        self.introLabel.setFont(font)

        # Create the index area.
        # Button - Text - Button

        # A frame to draw a line around the layout.
        self.indexBox = IndexBox()

        self.buttonPrevious = IndexButton("Previous")
        self.buttonPrevious.setEnabled(False)
        self.buttonPrevious.clicked.connect(self.previousImage)

        self.labelIndex = QLabel()
        self.labelIndex.setAlignment(Qt.AlignCenter)

        self.buttonNext = IndexButton("Next")
        self.buttonNext.setEnabled(False)
        self.buttonNext.clicked.connect(self.nextImage)

        frameLayout = QHBoxLayout()
        frameLayout.addWidget(self.buttonPrevious)
        frameLayout.addWidget(self.labelIndex)
        frameLayout.addWidget(self.buttonNext)

        self.indexBox.setLayout(frameLayout)

        # Create and add widgets to the main layout.
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.mainLayout.addWidget(self.introLabel)
        self.mainLayout.addWidget(self.indexBox)

        # Create central widget.
        centralWidget = QWidget()
        centralWidget.setLayout(self.mainLayout)
        self.setCentralWidget(centralWidget)

    def setupMenuBar(self):
        """
        Setup the application menu bar.
        """

        # Create the menu bar actions.
        self.createActions()
        menuBar = self.menuBar()

        fileMenu = menuBar.addMenu("&File")
        fileMenu.addAction(self.openFileAct)
        fileMenu.addAction(self.openDirAct)
        fileMenu.addSeparator()
        fileMenu.addAction(self.exitAct)

        viewMenu = menuBar.addMenu("&View")
        viewMenu.addAction(self.zoomInAct)
        viewMenu.addAction(self.zoomOutAct)
        viewMenu.addSeparator()
        viewMenu.addAction(self.normalSizeAct)
        viewMenu.addAction(self.fitToWindowAct)
        viewMenu.addAction(self.fullscreenAct)

    def createActions(self):
        """
        Create the actions for the application menu bar.
        """
        """ File menu actions. """
        self.openFileAct = QAction("&Open file..", self, shortcut="Ctrl+O")
        self.openFileAct.setToolTip("Select an image")
        self.openFileAct.triggered.connect(self.showFileDialog)

        self.openDirAct = QAction("&Choose directory..",
                                  self,
                                  shortcut="Ctrl+D")
        self.openDirAct.setToolTip("Choose a directory instead of a file")
        self.openDirAct.triggered.connect(self.showDirDialog)

        self.exitAct = QAction("&Exit", self, shortcut="Ctrl+Q")
        self.exitAct.setToolTip("Close the application..")
        self.exitAct.triggered.connect(self.close)
        """ View menu actions. """
        self.zoomInAct = QAction("&Zoom In", self, shortcut="Ctrl++")
        self.zoomInAct.setToolTip("Zoom in")

        self.zoomOutAct = QAction("&Zoom Out", self, shortcut="Ctrl+-")
        self.zoomOutAct.setToolTip("Zoom out")

        self.normalSizeAct = QAction("&Normal Size", self, shortcut="Ctrl+S")
        self.normalSizeAct.setToolTip("Reset zoom level")
        self.normalSizeAct.setEnabled(False)

        self.fitToWindowAct = QAction("&Fit Window",
                                      self,
                                      shortcut="Ctrl+F",
                                      checkable=True,
                                      triggered=self.fitImage)
        self.fitToWindowAct.setToolTip(
            "Resize image to fit the current window")

        self.fullscreenAct = QAction("&Fullscreen Mode",
                                     self,
                                     shortcut="F11",
                                     checkable=True,
                                     triggered=self.fullscreen)

        # Disable actions by default.
        self.zoomInAct.setEnabled(False)
        self.zoomOutAct.setEnabled(False)
        self.normalSizeAct.setEnabled(False)
        self.fitToWindowAct.setEnabled(False)

    def showFileDialog(self):
        """
        Open a file dialog that only allows the user to choose image files.
        Only supports .jpg and .png files for now.
        """

        # Transforms the list of extensions in a string
        # Something like: *.jpg *.png
        extensions = "*." + " *.".join(SUPPORTED_EXTENSIONS)

        # Open file dialog.
        # Returns a tuple, first element is the selected path.
        # Second element is the chosen filter.

        filePath = QFileDialog.getOpenFileName(
            parent=self,
            caption="Select an image file.",
            directory=os.path.expanduser("~"),
            filter="Image Files ({})".format(extensions),
        )[0]

        if not filePath:
            return

        self.loadImage(filePath)

    def showDirDialog(self):
        """
        Open a directory dialog.
        Also show files, but only directories can be selected.
        """
        path = QFileDialog.getExistingDirectory(
            parent=self,
            caption="Choose a directory",
            directory=os.path.expanduser("~"),
            options=QFileDialog.DontUseNativeDialog,
        )

        if not path:
            return

        # Scan the directory.
        self.scanDir(path)

        # Check if directory is empty.
        if not self.dirImages:
            QMessageBox.critical(self, "Error!", "No images were found!")
            return

        # Load the first image from the directory.
        self.loadImage(self.dirImages[0])

    def loadImage(self, imagePath: str):
        """
        Display image from `imagePath`.
        """

        # Load image. Converts to QPixmap automatically.
        self.imageView.setImage(imagePath)

        # Check fit status
        self.fitImage()

        # This will run only when the first image is loaded.
        if self.currentImage is None:
            # Replace the intro text with the image.
            self.mainLayout.replaceWidget(self.introLabel, self.imageView)

            # Enable buttons. They will be hidden/shown later.
            self.buttonPrevious.setEnabled(True)
            self.buttonNext.setEnabled(True)

        # Enable action.
        self.fitToWindowAct.setEnabled(True)

        # Store the current image.
        self.currentImage = imagePath

        # Scan the current image's directory.
        self.scanDir(os.path.dirname(self.currentImage))

        # Update the index
        self.updateIndex()

    def scanDir(self, path: str):
        """
        Scan the image's directory.
        """

        # Stores all files inside the directory.
        imageDir = QDir(path)
        imageDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.Readable)

        # Add files' absolute path to list.
        self.dirImages = [
            file.absoluteFilePath() for file in imageDir.entryInfoList()
            if file.suffix() in SUPPORTED_EXTENSIONS
        ]

    def updateIndex(self):
        index = self.dirImages.index(self.currentImage)
        total = len(self.dirImages)
        fileName = os.path.basename(self.currentImage)

        if index == 0:
            self.buttonPrevious.setHidden(True)
            self.buttonNext.setHidden(False)
        elif (index + 1) == total:
            self.buttonPrevious.setHidden(False)
            self.buttonNext.setHidden(True)
        else:
            self.buttonPrevious.setHidden(False)
            self.buttonNext.setHidden(False)

        text = f"{index + 1} of {total} - {fileName}"
        self.labelIndex.setText(text)

    def nextImage(self):
        index = self.dirImages.index(self.currentImage)
        self.loadImage(self.dirImages[index + 1])

    def previousImage(self):
        index = self.dirImages.index(self.currentImage)
        self.loadImage(self.dirImages[index - 1])

    def fitImage(self):
        fit = self.fitToWindowAct.isChecked()
        if fit:
            self.imageView.fitToWindow()
        else:
            self.imageView.showNormal()

    def fullscreen(self):
        if not self.isFullScreen():
            self.showFullScreen()
        else:
            self.showNormal()

    def resizeEvent(self, event):
        if self.currentImage is None:
            event.accept()

        fit = self.fitToWindowAct.isChecked()
        if fit:
            self.imageView.fitToWindow()
        else:
            self.imageView.showNormal()
Exemple #9
0
class QWPopupTableCheck(QWidget):
    """
    """
    def __init__(self, **kwargs):
        parent = kwargs.get('parent', None)
        QWidget.__init__(self, parent)

        self.kwargs = kwargs
        self.list2d_out = []

        win_title = kwargs.get('win_title', None)
        if win_title is not None: self.setWindowTitle(win_title)

        #self.wtab = QWTableOfCheckBoxes(**kwargs)
        self.wtab = CGWPartitionTable(**kwargs)
        #self.make_gui_checkbox()

        self.do_ctrl = kwargs.get('do_ctrl', True)
        self.do_frame = kwargs.get('do_frame', True)

        #self.but_update = QPushButton('&Update')
        #self.but_cancel = QPushButton('&Cancel')
        self.but_apply = QPushButton('&Apply')

        #self.but_update.clicked.connect(self.on_but_update)
        #self.but_cancel.clicked.connect(self.onCancel)
        self.but_apply.clicked.connect(self.onApply)

        self.hbox = QHBoxLayout()
        #self.hbox.addWidget(self.but_update)
        #self.hbox.addStretch(1)
        #self.hbox.addWidget(self.but_cancel)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.but_apply)

        self.vbox = QVBoxLayout()
        self.vbox.addWidget(self.wtab)
        self.vbox.addLayout(self.hbox)
        self.setLayout(self.vbox)

        self.setIcons()
        self.set_style()

#-----------------------------

    def set_style(self):
        #if not self.do_frame:
        #   self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        styleGray = "background-color: rgb(230, 240, 230); color: rgb(0, 0, 0);"  # Gray
        #styleTest = "background-color: rgb(100, 240, 200); color: rgb(0, 0, 0);"
        styleDefault = ""
        self.setStyleSheet(styleDefault)

        self.layout().setContentsMargins(0, 0, 0, 0)

        self.setMinimumWidth(100)
        #self.but_update.setFixedWidth(70)
        #self.but_cancel.setFixedWidth(70)
        self.but_apply.setFixedWidth(70)

        #self.but_update.setStyleSheet(styleGray)
        #self.but_update.setFocusPolicy(Qt.NoFocus)
        #self.but_cancel.setFocusPolicy(Qt.NoFocus)
        #self.but_cancel.setStyleSheet(styleGray)
        self.but_apply.setStyleSheet(styleGray)
        self.but_apply.setEnabled(self.do_ctrl)
        self.but_apply.setFlat(not self.do_ctrl)

        self.setSizePolicy(QSizePolicy.MinimumExpanding,
                           QSizePolicy.MinimumExpanding)

        self.wtab.setFixedHeight(self.wtab.height() + 2)
        self.setFixedWidth(max(self.wtab.width(), 285) + 2)

        #self.but_update.setVisible(False)
        #self.but_cancel.setVisible(False)

        #self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
        #self.setWindowFlags(Qt.Window | Qt.CustomizeWindowHint)

    def setIcons(self):
        try:
            from psdaq.control_gui.QWIcons import icon
            icon.set_icons()
            #self.but_cancel.setIcon(icon.icon_button_cancel)
            self.but_apply.setIcon(icon.icon_button_ok)
        except:
            pass

    #def on_but_update(self):
    def update_partition_table(self):
        logger.debug('update_partition_table')
        _, list2d = get_platform(
        )  # [[[True,''], 'test/19670/daq-tst-dev02', 'testClient2b'], ...]
        logger.debug('list2d\n', list2d)

        self.kwargs['tableio'] = list2d
        wtab = CGWPartitionTable(**self.kwargs)
        self.vbox.replaceWidget(self.wtab, wtab)
        #self.vbox.removeWidget(self.hbox)
        #self.vbox.addLayout(self.hbox)
        self.wtab.close()
        del self.wtab
        self.wtab = wtab
        self.set_style()

    #def onCancel(self):
    #    logger.debug('onCancel')
    #    self.reject()

    def onApply(self):
        logger.debug('onApply')
        self.list2d_out = self.wtab.fill_output_object()
        #self.accept()

        dict_platf, list2d = get_platform(
        )  # [[[True,''], 'test/19670/daq-tst-dev02', 'testClient2b'], ...]
        set_platform(dict_platf, self.list2d_out)

        ## 2019-03-13 caf: If Select->Apply is successful, an Allocate transition should be triggered.
        ## 2020-07-29 caf: The Allocate transition will update the active detectors file, if necessary.

        list2d_active = list_active_procs(self.list2d_out)

        if len(list2d_active) == 0:
            logger.warning('NO PROCESS SELECTED!')
        else:
            daq_control().setState('allocated')

    def table_out(self):
        return self.list2d_out
Exemple #10
0
class SongsTable_Container(FFrame):
    def __init__(self, app, parent=None):
        super().__init__(parent)
        self._app = app

        self.songs_table = None
        self.img_label = CoverImgLabel(self._app)
        self.desc_container = DescriptionContainer(self._app)
        self.info_container = FFrame(parent=self)
        self.table_control = TableControl(self._app)
        self._layout = QVBoxLayout(self)
        self._info_layout = QHBoxLayout(self.info_container)
        self.setup_ui()

    def setup_ui(self):
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)
        self._info_layout.setContentsMargins(0, 0, 0, 0)
        self._info_layout.setSpacing(0)

        self._info_layout.addWidget(self.img_label)
        self._info_layout.addSpacing(20)
        self._info_layout.addWidget(self.desc_container)

        self._layout.addSpacing(10)
        self._layout.addWidget(self.info_container)
        self._layout.addSpacing(10)
        self._layout.addWidget(self.table_control)

    def set_table(self, songs_table):
        if self.songs_table:
            self._layout.replaceWidget(self.songs_table, songs_table)
            self.songs_table.deleteLater()
        else:
            self._layout.addWidget(songs_table)
            self._layout.addSpacing(10)
        self.songs_table = songs_table

    def load_img(self, img_url, img_name):
        self.info_container.show()
        event_loop = asyncio.get_event_loop()
        future = event_loop.create_task(
            self._app.img_ctl.get(img_url, img_name))
        future.add_done_callback(self.set_img)

    def set_img(self, future):
        content = future.result()
        img = QImage()
        img.loadFromData(content)
        pixmap = QPixmap(img)
        if pixmap.isNull():
            return None
        self.img_label.setPixmap(
            pixmap.scaledToWidth(self.img_label.width(),
                                 mode=Qt.SmoothTransformation))

    def set_desc(self, desc):
        self.desc_container.set_html(desc)

    def hide_info_container(self):
        self.info_container.hide()
Exemple #11
0
class ColumnEditor(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.column = None
        pal = self.palette()
        pal.setColor(QPalette.Background,
                     QColor(self.palette().base().color().name()).lighter())
        self.setPalette(pal)
        self.setAutoFillBackground(True)

        self.layout = QVBoxLayout()
        self.layout.setAlignment(Qt.AlignTop)
        self.setLayout(self.layout)
        self.setAcceptDrops(True)

        ee = ElementEditor()
        self.layout.addWidget(ee, 0, Qt.AlignTop)
        ee.elementEnabled.connect(self.addElement)
        ee.elementDragged.connect(self.addElement)
        # connect(ee, SIGNAL(elementCopied(ElementEditor*)), this, SLOT(copyElement(ElementEditor*)));

    def addElement(self):
        ee = ElementEditor()
        self.layout.addWidget(ee, 0, Qt.AlignTop)

        ce = self.getContentEditor()
        if ce:
            ce.editChanged("Add Element")

        ee.elementEnabled.connect(self.addElement)
        ee.elementDragged.connect(self.addElement)

        # connect(ee, SIGNAL(elementCopied(ElementEditor*)), this, SLOT(copyElement(ElementEditor*)));

    def addElementEditor(self, ee):
        self.layout.insertWidget(self.layout.count() - 1, ee, 0, Qt.AlignTop)
        ee.elementEnabled.connect(self.addElement)
        ee.elementDragged.connect(self.addElement)

        #connect(ee, SIGNAL(elementCopied(ElementEditor*)), this, SLOT(copyElement(ElementEditor*)));

    def getContentEditor(self):
        from widgets.pageeditor import PageEditor
        from widgets.roweditor import RowEditor
        from widgets.sectioneditor import SectionEditor
        re = self.parentWidget()
        if isinstance(re, RowEditor):
            se = re.parentWidget()
            if isinstance(se, SectionEditor):
                pe = se.parentWidget()
                if isinstance(pe, PageEditor):
                    sa = pe.parentWidget()
                    if sa:
                        vp = sa.parentWidget()
                        if vp:
                            cee = vp.parentWidget()
                            if cee:
                                return cee

        return None

    def load(self, column):
        self.column = column
        for item in self.column.items:
            ee = ElementEditor()
            ee.setMode(Mode.ENABLED)
            ee.setContent(item)
            ee.elementEnabled.connect(self.addElement)
            ee.elementDragged.connect(self.addElement)

            #connect(ee, SIGNAL(elementCopied(ElementEditor*)), this, SLOT(copyElement(ElementEditor*)));
            self.layout.insertWidget(self.layout.count() - 1, ee, 0,
                                     Qt.AlignTop)

    def dragEnterEvent(self, event):
        myData = event.mimeData()
        if myData:
            ee = myData.getData()
            if isinstance(ee, ElementEditor):
                for i in range(self.layout.count()):
                    editor = self.layout.itemAt(i).widget()
                    if isinstance(editor,
                                  ElementEditor) and editor.mode == Mode.EMPTY:
                        editor.setMode(Mode.DROPZONE)
                        break
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def dragLeaveEvent(self, event):
        for i in range(self.layout.count()):
            editor = self.layout.itemAt(i).widget()
            if isinstance(editor,
                          ElementEditor) and editor.mode == Mode.DROPZONE:
                # put editor to the end of the list
                editor.setMode(Mode.EMPTY)
                self.layout.removeWidget(editor)
                self.layout.addWidget(editor)
                break
        event.accept()

    def dragMoveEvent(self, event):
        myData = event.mimeData()
        if myData:
            ee = myData.getData()
            if isinstance(ee, ElementEditor):
                row = event.pos().y() / 50  #+ self.layout.margin())
                for i in range(self.layout.count()):
                    editor = self.layout.itemAt(i).widget()
                    if isinstance(
                            editor,
                            ElementEditor) and editor.mode == Mode.DROPZONE:
                        if i != row:
                            # put dropzone under mouse pointer
                            self.layout.insertWidget(row, editor)
                        break
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def dropEvent(self, event):
        myData = event.mimeData()
        if myData:
            ee = myData.getData()
            if isinstance(ee, ElementEditor):
                for i in range(self.layout.count()):
                    dz = self.layout.itemAt(i).widget()
                    if isinstance(dz,
                                  ElementEditor) and dz.mode == Mode.DROPZONE:
                        # remove widget if it belongs to this layout
                        self.layout.removeWidget(ee)

                        # replace dropzone with dragged element
                        self.layout.replaceWidget(dz, ee)
                        new_pos = i
                        # and put dropzone to the end of the list
                        dz.setMode(Mode.EMPTY)
                        self.layout.removeWidget(dz)
                        self.layout.addWidget(dz)
                        break
                ee.dropped()
                ee.show()
                ee.elementEnabled.disconnect()
                ee.elementDragged.disconnect()
                # ee.copied.disconnect(self.copyElement)
                ce = self.getContentEditor()
                if ce:
                    myData.source_list.remove(ee.content)
                    self.column.insertElement(ee.content, new_pos)
                    ce.editChanged("Move Element")
                ee.elementEnabled.connect(self.addElement)
                ee.elementDragged.connect(self.addElement)
                # ee.elementCopied.connectself.copyElement)
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def removeElement(self, content):
        self.column._items.remove(content)
Exemple #12
0
class EphemerisDialog(QDialog):
    def __init__(self, app: EphemerisApp, parent=None):
        super(EphemerisDialog, self).__init__(parent)
        self.offset = QPoint()
        self.ephemeris = app
        self.app = app.app_ctx
        self._header_title = 'E P H E M E R I S'
        self.google_service = GoogleService(self.app)

        self._main_layout = QVBoxLayout()
        self._main_layout.addLayout(self._create_head())
        self._bottom_btn = QPushButton()
        self._current_view = self._get_start_view()
        self._main_layout.addWidget(self._current_view)
        self._main_layout.addWidget(self._bottom_btn)
        self.setLayout(self._main_layout)
        self.setFixedWidth(230)
        self._set_flags()

    def switch_current_view(self, new: EphemerisGroupBox):
        self._main_layout.replaceWidget(self._current_view, new)
        self._current_view.deleteLater()
        self._current_view = new
        self._switch_button(new)
        self.refresh()
        self.raise_()
        self.activateWindow()

    def refresh(self):
        self.setVisible(False)
        self.setVisible(True)

    def _switch_button(self, group):
        self._bottom_btn.setText(group.button_label)
        self._bottom_btn.setIcon(QIcon() if group.button_icon is None else group.button_icon)
        try:
            self._bottom_btn.disconnect()
        except():
            pass
        self._bottom_btn.clicked.connect(group.button_click)
        self._bottom_btn.setFocus()

    def _get_start_view(self):
        if not self.google_service.is_token_exists():
            group = LoginGroupBox(self)
            self._switch_button(group)
            return group
        else:
            self.google_service.prepare_credentials()
            self.google_service.build_resource()
            group = InputGroupBox(self)
            self._switch_button(group)
            return group

    def _set_flags(self):
        self.setWindowFlag(Qt.WindowStaysOnTopHint)
        self.setWindowFlag(Qt.FramelessWindowHint)

    def _create_head(self):
        logo = QLabel()
        logo.setPixmap(get_QPixmap(self.app, 'logo_transparent_tiny.png'))
        label = QLabel(self._header_title)
        logo.setBuddy(label)

        header = QHBoxLayout()
        self._setup_header_widgets()
        header.addWidget(logo)
        header.addWidget(label)
        header.addStretch(2)
        header.addWidget(self.cog)
        return header

    def _setup_header_widgets(self):
        self.cog = PicButton(self.app, 'cog.png')
        self.cog.setContextMenuPolicy(Qt.CustomContextMenu)

        self.menu = QMenu()
        self.quit_a = QAction("Quit")
        self.pin_a = QAction("Pin")
        self.menu.addAction(self.pin_a)
        self.menu.addSeparator()
        self.menu.addAction(self.quit_a)
        self.pin_a.triggered.connect(self._on_pin_click)
        self.quit_a.triggered.connect(self.app.app.quit)

        self.cog.setMenu(self.menu)

    def _on_cog_click(self, point):
        self.menu.exec_(self.cog.mapToGlobal(point))

    def _on_pin_click(self):
        self.ephemeris.is_pinned = not self.ephemeris.is_pinned
        text = 'Unpin' if self.ephemeris.is_pinned else 'Pin'
        self.pin_a.setText(text)
        print(f'set to {self.ephemeris.is_pinned}')
        self.show()

    def mousePressEvent(self, event):
        self.offset = event.pos()

    def mouseMoveEvent(self, event):
        x = event.globalX()
        y = event.globalY()
        x_w = self.offset.x()
        y_w = self.offset.y()
        self.move(x - x_w, y - y_w)
Exemple #13
0
class MainWindow(QWidget):
    def __init__(self, windowsManager, parent=None):
        super().__init__(parent)
        self.windowsManager = windowsManager

        # 툴바 레이아웃. 상단에 단어 정렬, 설정, 외우기모드 시작 버튼 등
        # 조작할 수 있는 것들을 모아둠.
        toolbarLayout = QGridLayout()

        memorizeStartBt = self.windowsManager.qButtonMaker(
            "Memorize Start", self.buttonClicked, None,
            (QSizePolicy.Expanding, QSizePolicy.Expanding))
        toolbarLayout.addWidget(memorizeStartBt, 0, 0, 3, 1)

        self.wordStandardCB = QComboBox()
        self.wordStandardCBStarted = False
        self.wordStandardCB.currentIndexChanged.connect(
            self.wordStandardCBChanged)
        self.wordStandardCB.addItems(["모두", "집중 단어만", "집중 단어 아닌것만"])

        self.sortStandardCB = QComboBox()
        self.sortStandardCBStarted = False
        self.sortStandardCB.currentIndexChanged.connect(
            self.sortStandardCBChanged)
        self.sortStandardCB.addItems(
            ["저장순", "영어 오름차순", "영어 내림차순", "한글 오름차순", "한글 내림차순"])

        settingBt = self.windowsManager.qButtonMaker(
            "설정", self.buttonClicked, None,
            (QSizePolicy.Expanding, QSizePolicy.Expanding))

        toolbarLayout.addWidget(self.wordStandardCB, 0, 1)
        toolbarLayout.addWidget(self.sortStandardCB, 1, 1)
        toolbarLayout.addWidget(settingBt, 2, 1)

        # 단어 레이아웃. 단어들 보여줌.
        self.focusedWordHint = QCheckBox()
        self.focusedWordHint.setText("= 집중 단어")
        self.focusedWordHint.setChecked(True)
        self.focusedWordHint.setDisabled(True)

        self.wordListLayout = QVBoxLayout()
        self.wordsScrollArea = QScrollArea()
        self.wordListLayout.addWidget(self.wordsScrollArea)
        self.updateWordListUI()

        # 단어 추가 레이아웃.
        wordAddLayout = QHBoxLayout()

        wordAddLayoutLeft = QGridLayout()

        sz = (200, 90)
        self.wordAddEnTE = self.windowsManager.qTextWidgetSetter(
            QTextEdit(), "", False, Qt.AlignLeft, sz)
        self.wordAddKoTE = self.windowsManager.qTextWidgetSetter(
            QTextEdit(), "", False, Qt.AlignLeft, sz)
        wordAddLayoutLeft.addWidget(QLabel("영어"), 0, 0)
        wordAddLayoutLeft.addWidget(self.wordAddEnTE, 1, 0)
        wordAddLayoutLeft.addWidget(QLabel("한글"), 0, 1)
        wordAddLayoutLeft.addWidget(self.wordAddKoTE, 1, 1)

        wordAddLayout.addLayout(wordAddLayoutLeft)

        wordAddLayoutRight = QGridLayout()
        wordAddBt = self.windowsManager.qButtonMaker(
            "추가", self.buttonClicked, None,
            (QSizePolicy.Expanding, QSizePolicy.Expanding))
        wordDeleteBt = self.windowsManager.qButtonMaker(
            "삭제", self.buttonClicked, None,
            (QSizePolicy.Expanding, QSizePolicy.Expanding))
        wordStringClearBt = self.windowsManager.qButtonMaker(
            "취소", self.buttonClicked, None,
            (QSizePolicy.Expanding, QSizePolicy.Expanding))
        wordAddLayoutRight.addWidget(wordAddBt, 0, 0)
        wordAddLayoutRight.addWidget(wordDeleteBt, 2, 0)
        wordAddLayoutRight.addWidget(wordStringClearBt, 3, 0)

        wordAddLayout.addLayout(wordAddLayoutRight)
        wordAddLayout.setSizeConstraint(QLayout.SetFixedSize)

        mainLayout = QGridLayout()
        mainLayout.setSizeConstraint(QLayout.SetFixedSize)
        mainLayout.addLayout(toolbarLayout, 0, 0)
        mainLayout.addLayout(self.wordListLayout, 1, 0)
        mainLayout.addLayout(wordAddLayout, 2, 0)

        self.setLayout(mainLayout)
        self.setWindowTitle('Memorize Words')

    def showWindow(self):
        self.show()
        self.move(500, 100)

    def wordAdd(self):
        en, ko = self.stripWordAddTextEdits()

        if en == "" and ko == "":
            return
        elif en == "":
            self.MessagingError("이름이 입력되지 않았습니다.")
            return
        elif ko == "":
            self.MessagingError("뜻이 입력되지 않았습니다.")
            return

        wordStandard = self.wordStandardCB.currentText()
        isFocused = False
        if wordStandard == "모두":
            wordStandardJudge = self.wordStandardJudgeWhoWantAll
        elif wordStandard == "집중 단어만":
            wordStandardJudge = self.wordStandardJudgeWhoWantFocused
            isFocused = True
        elif wordStandard == "집중 단어 아닌것만":
            wordStandardJudge = self.wordStandardJudgeWhoWantNotFocused
        else:
            self.MessagingError("알수 없는 오류가 발생했습니다: wordStandard에 \'" +
                                wordStandard + "\'이 없음")
            return

        word = Word(en, ko, (isFocused, self.windowsManager.dataManager))
        self.windowsManager.dataManager.wordAdd(word)
        self.wordAddTextClear()
        self.updateListedWords()

    def stripWordAddTextEdits(self):
        en = self.wordAddEnTE.toPlainText().strip()
        ko = self.wordAddKoTE.toPlainText().strip()

        self.wordAddEnTE.setText(en)
        self.wordAddKoTE.setText(ko)
        return en, ko

    def wordAddTextClear(self):
        self.wordAddEnTE.clear()
        self.wordAddKoTE.clear()

    def wordDeleteButtonClicked(self):
        en, ko = self.stripWordAddTextEdits()

        enEmpty = False
        koEmpty = False

        if en == "":
            enEmpty = True
        if ko == "":
            koEmpty = True

        if enEmpty and koEmpty:
            # 아무 것도 안적은 상태라면 아무 행동도 하지 않음.
            return

        if not enEmpty and not koEmpty:
            # 둘다 적혀 있다면, 두 개가 가리키는 영단어가
            # 같은지 확인, 같다면 지우고 다르다면 에러 메시지.
            ws_en = self.findWordsAtNowListedWordsByEn(en)
            ws_ko = self.findWordsAtNowListedWordsByKo(ko)

            # 단어가 없다면 에러 메시지.
            if len(ws_en) == 0 or len(ws_ko) == 0:
                self.MessagingError("\'" + en + " " + ko + "\'는 없는 단어입니다!")
                return

            willDelete = []
            for w in ws_en:
                if w in ws_ko:
                    willDelete.append(w)
            if len(willDelete) == 0:
                self.MessagingError("단어의 이름과 뜻이 다릅니다!")
            else:
                for w in willDelete:
                    self.wordDelete(w)
        else:
            if not enEmpty:
                # 영어만 채워져 있다면, 같은 이름의 모든 단어 삭제
                ws_en = self.findWordsAtNowListedWordsByEn(en)
                if len(ws_en) == 0:
                    self.MessagingError("\'" + en + "\'이 현재 리스트에 없습니다!")
                else:
                    for w in ws_en:
                        self.wordDelete(w)
            else:
                # 한글만 채워져 있다면, 같은 뜻의 모든 단어 삭제
                ws_ko = self.findWordsAtNowListedWordsByKo(ko)
                if len(ws_ko) == 0:
                    self.MessagingError("\'" + ko + "\'이 현재 리스트에 없습니다!")
                else:
                    for w in ws_ko:
                        self.wordDelete(w)

    def wordDelete(self, word):
        en, ko = word.getStrings()
        print("Delete", en, ko)
        try:
            self.windowsManager.getNowListedWords().remove(word)
            self.windowsManager.dataManager.wordDelete(word)
            self.MessagingSuccess('\'' + en + ' ' + ko + "\'가 삭제되었습니다.")
            self.wordAddTextClear()
        except:
            self.MessagingError("없는 단어입니다.")

        self.updateListedWords()

    def MessagingSuccess(self, content):
        QMessageBox.about(self, "Success", content)

    def MessagingError(self, content):
        QMessageBox.about(self, "Error", content)

    def findWordsAtNowListedWordsByEn(self, en):
        ws = []
        for w in self.windowsManager.getNowListedWords():
            w_en, w_ko = w.getStrings()
            if w_en == en:
                ws.append(w)
        return ws

    def findWordsAtNowListedWordsByKo(self, ko):
        ws = []
        for w in self.windowsManager.getNowListedWords():
            w_en, w_ko = w.getStrings()
            if w_ko == ko:
                ws.append(w)
        return ws

    def wordStandardCBChanged(self, i):
        if not self.wordStandardCBStarted:
            self.wordStandardCBStarted = True
            return

        print("wordStandardCB current", self.wordStandardCB.currentText())
        self.updateListedWords()

    def sortStandardCBChanged(self, i):
        if not self.sortStandardCBStarted:
            self.sortStandardCBStarted = True
            return

        print("sortStandardCBChanged", i)
        self.updateListedWords()

    def updateListedWords(self):
        wordStandard = self.wordStandardCB.currentText()

        if wordStandard == "모두":
            wordStandardJudge = self.wordStandardJudgeWhoWantAll
        elif wordStandard == "집중 단어만":
            wordStandardJudge = self.wordStandardJudgeWhoWantFocused
        elif wordStandard == "집중 단어 아닌것만":
            wordStandardJudge = self.wordStandardJudgeWhoWantNotFocused
        else:
            print("wordStandard가 존재하지 않는 값입니다!:", wordStandard)
            return

        sortStandard = self.sortStandardCB.currentText()

        words = self.windowsManager.getAllWords()
        judgedWords = []
        for w in words:
            if wordStandardJudge(w):
                judgedWords.append(w)

        if sortStandard == "저장순":
            pass
        elif sortStandard == "영어 오름차순":
            judgedWords = sorted(
                judgedWords,
                key=lambda x: self.sortStandardJudgeWhoWantEn(x),
                reverse=False)
        elif sortStandard == "영어 내림차순":
            judgedWords = sorted(
                judgedWords,
                key=lambda x: self.sortStandardJudgeWhoWantEn(x),
                reverse=True)
        elif sortStandard == "한글 오름차순":
            judgedWords = sorted(
                judgedWords,
                key=lambda x: self.sortStandardJudgeWhoWantKo(x),
                reverse=False)
        elif sortStandard == "한글 내림차순":
            judgedWords = sorted(
                judgedWords,
                key=lambda x: self.sortStandardJudgeWhoWantKo(x),
                reverse=True)
        else:
            print("sortStandard가 존재하지 않는 값입니다!:", sortStandard)
            return

        self.windowsManager.setNowListedWords(judgedWords)

        self.updateWordListUI()

    def wordStandardJudgeWhoWantAll(self, word):
        return True

    def wordStandardJudgeWhoWantFocused(self, word):
        return word.getIsFocusing()

    def wordStandardJudgeWhoWantNotFocused(self, word):
        return not word.getIsFocusing()

    def sortStandardJudgeWhoWantEn(self, word):
        en, ko = word.getStrings()
        return en

    def sortStandardJudgeWhoWantKo(self, word):
        en, ko = word.getStrings()
        return ko

    def updateWordListUI(self):
        wordsLayout = QVBoxLayout()
        wordsLayout.addWidget(self.focusedWordHint)

        self.focusedCheckboxWithWord = {}

        for w in self.windowsManager.getNowListedWords():
            oneWordLayout = QHBoxLayout()

            cb = QCheckBox()
            cb.setChecked(w.getIsFocusing())

            en, ko = w.getStrings()

            wdEn = self.windowsManager.qTextWidgetSetter(
                QTextEdit(), en, True, Qt.AlignLeft, None,
                (QSizePolicy.Expanding, QSizePolicy.Fixed))
            wdKo = self.windowsManager.qTextWidgetSetter(
                QTextEdit(), ko, True, Qt.AlignLeft, None,
                (QSizePolicy.Expanding, QSizePolicy.Fixed))
            wdEn.setFixedHeight(55)
            wdKo.setFixedHeight(55)

            wdEn.selectionChanged.connect(self.wordEnClicked)
            wdKo.selectionChanged.connect(self.wordKoClicked)

            cb.clicked.connect(self.focusedCheckboxClicked)
            oneWordLayout.addWidget(cb)
            oneWordLayout.addWidget(wdEn)
            oneWordLayout.addWidget(wdKo)
            wordsLayout.addLayout(oneWordLayout)

            self.focusedCheckboxWithWord[cb] = w

        wordsLayout.addStretch()

        groupBox = QGroupBox()
        groupBox.setLayout(wordsLayout)
        wordsScrollAreaNew = QScrollArea()
        wordsScrollAreaNew.setWidget(groupBox)
        wordsScrollAreaNew.setWidgetResizable(True)
        wordsScrollAreaNew.setFixedSize(550, 550)

        self.wordListLayout.replaceWidget(self.wordsScrollArea,
                                          wordsScrollAreaNew)
        self.wordsScrollArea = wordsScrollAreaNew

    def focusedCheckboxClicked(self, val):
        word = self.focusedCheckboxWithWord[self.sender()]
        en, ko = word.getStrings()
        print("Set Focused", val, en, ko)
        word.setIsFocusing(val, self.windowsManager.dataManager)
        self.updateListedWords()

    def buttonClicked(self):
        bt = self.sender().text()

        if bt == "Memorize Start":
            self.windowsManager.memorizeModeStart()
        elif bt == "추가":
            self.wordAdd()
        elif bt == "삭제":
            self.wordDeleteButtonClicked()
        elif bt == "취소":
            self.wordAddTextClear()
        elif bt == "설정":
            self.windowsManager.settingWindow.show()

    def wordEnClicked(self):
        txt = self.sender().toPlainText()
        self.wordAddEnTE.setText(txt)

    def wordKoClicked(self):
        txt = self.sender().toPlainText()
        self.wordAddKoTE.setText(txt)
Exemple #14
0
class SongsTable_Container(FFrame):
    def __init__(self, app, parent=None):
        super().__init__(parent)
        self._app = app

        self.songs_table = None
        self.img_label = CoverImgLabel(self._app)
        self.desc_container = DescriptionContainer(self._app)
        self.info_container = FFrame(parent=self)
        self.table_control = TableControl(self._app)
        self._layout = QVBoxLayout(self)
        self._info_layout = QHBoxLayout(self.info_container)
        self.setup_ui()

    def setup_ui(self):
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(0)
        self._info_layout.setContentsMargins(0, 0, 0, 0)
        self._info_layout.setSpacing(0)

        self._info_layout.addWidget(self.img_label)
        self._info_layout.addSpacing(20)
        self._info_layout.addWidget(self.desc_container)

        self._layout.addSpacing(10)
        self._layout.addWidget(self.info_container)
        self._layout.addSpacing(10)
        self._layout.addWidget(self.table_control)

    def set_table(self, songs_table):
        if self.songs_table:
            self._layout.replaceWidget(self.songs_table, songs_table)
            self.songs_table.deleteLater()
        else:
            self._layout.addWidget(songs_table)
            self._layout.addSpacing(10)
        self.songs_table = songs_table

    def load_img(self, img_url, img_name):
        self.info_container.show()
        event_loop = asyncio.get_event_loop()
        future = event_loop.create_task(
            self._app.img_ctl.get(img_url, img_name))
        future.add_done_callback(self.set_img)

    def set_img(self, future):
        content = future.result()
        img = QImage()
        img.loadFromData(content)
        pixmap = QPixmap(img)
        if pixmap.isNull():
            return None
        self.img_label.setPixmap(
            pixmap.scaledToWidth(self.img_label.width(),
                                 mode=Qt.SmoothTransformation))

    def set_desc(self, desc):
        self.desc_container.set_html(desc)

    def hide_info_container(self):
        self.info_container.hide()
Exemple #15
0
class MainPanel(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Compound Exercises"
        self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }
    QComboBox{
      border-radius: 4px;
      font-size: 18px;
      font-weight: bold;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
      min-height: 28px;
      background-color: #440D0F;
    }
    QComboBox:down-arrow{
      width: 0px;
      height: 0px;
      background: #d3d3d3; 
      opacity:0
    }
    QComboBox:drop-down{
      background-color: #440D0F;
      border: 0px;
      opacity:0;
      border-radius: 0px;
      width: 0px;
      height: 0px;
    }
    QComboBox:hover:!pressed{
      background-color: #5D1A1D;
    }
    QComboBox:pressed{
      background-color: #551812;
    }
    """)
        self.current_year = str(datetime.now().year)
        self.db_wrapper.create_local_table(self.table_name)
        if self.db_wrapper.local_table_is_empty(self.table_name):
            self.db_wrapper.insert_default_values(self.table_name)

        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        big_lifts_units = "kg" if self.db_wrapper.fetch_local_column(
            self.table_name, "units") == "metric" else "lb"

        one_rep_maxes = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "one_rep_maxes"))
        lifts_for_reps = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "lifts_for_reps"))
        self.rm_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name, "rm_history"))

        if not self.current_year in self.rm_history:
            self.add_year_to_rm_history(self.current_year)
            self.rm_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "rm_history"))

        if self.units != big_lifts_units:
            units_name = "metric" if self.units == "kg" else "imperial"
            self.db_wrapper.update_table_column(self.table_name, "units",
                                                units_name)
            if units_name == "metric":
                for exercise, weight in one_rep_maxes.items():
                    one_rep_maxes[exercise] = str(pounds_to_kg(weight))
                for exercise, reps_and_weight in lifts_for_reps.items():
                    lifts_for_reps[exercise] = [
                        reps_and_weight[0],
                        str(pounds_to_kg(reps_and_weight[1]))
                    ]

            elif units_name == "imperial":
                for exercise, weight in one_rep_maxes.items():
                    one_rep_maxes[exercise] = str(kg_to_pounds(weight))
                for exercise, reps_and_weight in lifts_for_reps.items():
                    lifts_for_reps[exercise] = [
                        reps_and_weight[0],
                        str(kg_to_pounds(reps_and_weight[1]))
                    ]

            for year in self.rm_history:
                for month in self.rm_history[year]:
                    for exercise_type in list(self.rm_history[year][month]):
                        for exercise in list(
                                self.rm_history[year][month][exercise_type]):
                            for i, weight in enumerate(
                                    self.rm_history[year][month][exercise_type]
                                [exercise]):
                                if units_name == "imperial":
                                    self.rm_history[year][month][
                                        exercise_type][exercise][i] = str(
                                            kg_to_pounds(weight))
                                elif units_name == "metric":
                                    self.rm_history[year][month][
                                        exercise_type][exercise][i] = str(
                                            pounds_to_kg(weight))

            self.db_wrapper.update_table_column(self.table_name,
                                                "one_rep_maxes", one_rep_maxes)
            self.db_wrapper.update_table_column(self.table_name,
                                                "lifts_for_reps",
                                                lifts_for_reps)
            self.convert_lift_history_weight(self.units)

        self.one_RM = [[lift, " ".join([weight, self.units])]
                       for lift, weight in one_rep_maxes.items()]
        self.lifts_reps = [[lift, " ".join(["x".join(weight), self.units])]
                           for lift, weight in lifts_for_reps.items()]

        self.lift_history_window = LiftHistory()
        self.lift_history_window.setGeometry(100, 200, 300, 300)

        self.plists_window = PreferredLifts()
        self.plists_window.change_lifts_signal.connect(
            self.changed_preferred_lifts)

        self.update_1RM_window = Update1RMWindow()
        self.update_1RM_window.change_1RM_lifts_signal.connect(
            self.changed_1RM_lifts)
        self.update_1RM_window.history_signal.connect(
            lambda signal: self.lift_history_window.create_history(signal))
        self.update_1RM_window.update_graph_signal.connect(
            lambda signal: self.refresh_graph(signal))

        self.lifts_for_reps = UpdateLiftsForRepsWindow()
        self.lifts_for_reps.change_lifts_for_reps_signal.connect(
            self.changed_lifts_for_reps)
        self.lifts_for_reps.history_signal.connect(
            lambda signal: self.lift_history_window.create_history(signal))

        self.preferred_lifts = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "preferred_lifts"))
        self.one_rep_maxes = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "one_rep_maxes"))
        self.create_panel()

    def create_panel(self):
        main_panel_grid = QGridLayout()
        main_panel_grid.addLayout(self.description(), 0, 0, 1, 1)
        main_panel_grid.addWidget(self.create_time_graph(), 1, 0, 4, 1)
        main_panel_grid.addLayout(self.create_bottom_layout(), 5, 0, 3, 1)
        main_panel_grid.addLayout(self.create_function_buttons(), 8, 0, 1, 1)
        self.setLayout(main_panel_grid)

    def description(self):
        panel_description = QVBoxLayout()
        desc_font = QFont("Montserrat", 12)
        description_label = QLabel(
            "Keep notes and track progress of your preferred big lifts here.",
            self)
        description_label.setFont(desc_font)
        description_label.setFixedHeight(20)
        panel_description.addWidget(description_label)
        return panel_description

    def create_time_graph(self):
        self.graph_layout = QVBoxLayout()

        graph = OneRMGraphCanvas("Horizontal Press", self.rm_history,
                                 self.current_year, self)

        combobox_layout = QHBoxLayout()
        self.lifts_combobox = QComboBox(self)
        self.lifts_combobox.addItems(list(self.preferred_lifts.values()))
        self.lifts_combobox.currentTextChanged.connect(
            lambda lift: self.change_exercise_graph(lift))

        self.change_year_combobox = QComboBox(self)
        self.change_year_combobox.addItems(list(self.rm_history.keys()))
        self.change_year_combobox.setCurrentText(self.current_year)
        self.change_year_combobox.currentTextChanged.connect(
            lambda year: self.change_graph_year(year))

        combobox_layout.addWidget(self.change_year_combobox)
        combobox_layout.addWidget(self.lifts_combobox)

        toolbar = NavigationToolbar(graph, self)
        toolbar.setStyleSheet("background-color: white;")

        self.graph_layout.addWidget(toolbar)
        self.graph_layout.addWidget(graph)
        self.graph_layout.addLayout(combobox_layout)

        framed_graph = QFrame(self)
        framed_graph.setFrameStyle(QFrame.Box)
        framed_graph.setLineWidth(3)
        framed_graph.setLayout(self.graph_layout)

        return framed_graph

    def create_bottom_layout(self):
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.create_one_rep_max())
        bottom_layout.addWidget(self.create_lifts_for_reps())
        return bottom_layout

    def create_one_rep_max(self):
        orm_panel = QVBoxLayout()
        main_label = QLabel("One Rep Max")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        self.horizontal_press_label_ORM = QLabel(": ".join(self.one_RM[0]))
        self.horizontal_press_label_ORM.setFont(QFont("Ariel", 10))

        self.floor_pull_label_ORM = QLabel(": ".join(self.one_RM[1]))
        self.floor_pull_label_ORM.setFont(QFont("Ariel", 10))

        self.squat_label_ORM = QLabel(": ".join(self.one_RM[2]))
        self.squat_label_ORM.setFont(QFont("Ariel", 10))

        self.vertical_press_label_ORM = QLabel(": ".join(self.one_RM[3]))
        self.vertical_press_label_ORM.setFont(QFont("Ariel", 10))

        orm_buttons = QHBoxLayout()
        update_button = QPushButton("Update")
        update_button.clicked.connect(lambda: self.update_1RM_window.show())
        clear_button = QPushButton("Clear")
        clear_button.clicked.connect(lambda: self.clear_one_rep_maxes())
        orm_buttons.addWidget(update_button)
        orm_buttons.addWidget(clear_button)

        orm_panel.addWidget(main_label)
        orm_panel.addWidget(self.horizontal_press_label_ORM)
        orm_panel.addWidget(self.floor_pull_label_ORM)
        orm_panel.addWidget(self.squat_label_ORM)
        orm_panel.addWidget(self.vertical_press_label_ORM)
        orm_panel.addLayout(orm_buttons)

        orm_panel.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")
        framed_layout.setLayout(orm_panel)

        return framed_layout

    def create_lifts_for_reps(self):
        reps_panel = QVBoxLayout()
        main_label = QLabel("Lifts For Reps")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        self.horizontal_press_label_reps = QLabel(": ".join(
            self.lifts_reps[0]))
        self.horizontal_press_label_reps.setFont(QFont("Ariel", 10))

        self.floor_pull_label_reps = QLabel(": ".join(self.lifts_reps[1]))
        self.floor_pull_label_reps.setFont(QFont("Ariel", 10))

        self.squat_label_reps = QLabel(": ".join(self.lifts_reps[2]))
        self.squat_label_reps.setFont(QFont("Ariel", 10))

        self.vertical_press_label_reps = QLabel(": ".join(self.lifts_reps[3]))
        self.vertical_press_label_reps.setFont(QFont("Ariel", 10))

        reps_buttons = QHBoxLayout()
        update_button = QPushButton("Update")
        update_button.clicked.connect(lambda: self.lifts_for_reps.show())
        clear_button = QPushButton("Clear")
        clear_button.clicked.connect(lambda: self.clear_lifts_for_reps())
        reps_buttons.addWidget(update_button)
        reps_buttons.addWidget(clear_button)

        reps_panel.addWidget(main_label)
        reps_panel.addWidget(self.horizontal_press_label_reps)
        reps_panel.addWidget(self.floor_pull_label_reps)
        reps_panel.addWidget(self.squat_label_reps)
        reps_panel.addWidget(self.vertical_press_label_reps)
        reps_panel.addLayout(reps_buttons)

        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")
        framed_layout.setLayout(reps_panel)

        return framed_layout

    def create_function_buttons(self):
        buttons_panel = QHBoxLayout()
        lift_history_button = QPushButton()
        lift_history_button.setText("Lift History")
        lift_history_button.clicked.connect(
            lambda: self.lift_history_window.show())
        preferred_lists_button = QPushButton()
        preferred_lists_button.setText("Preferred Lifts")
        preferred_lists_button.clicked.connect(
            lambda: self.plists_window.show())

        buttons_panel.addWidget(lift_history_button)
        buttons_panel.addWidget(preferred_lists_button)
        return buttons_panel

    @pyqtSlot(bool)
    def changed_preferred_lifts(self, changed):
        if changed:
            self.preferred_lifts = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "preferred_lifts"))
            parsed_lifts = list(self.preferred_lifts.values())

            one_RM_labels = [
                self.horizontal_press_label_ORM, self.floor_pull_label_ORM,
                self.squat_label_ORM, self.vertical_press_label_ORM
            ]

            lifts_for_reps_labels = [
                self.horizontal_press_label_reps, self.floor_pull_label_reps,
                self.squat_label_reps, self.vertical_press_label_reps
            ]

            for i, label in enumerate(one_RM_labels):
                label_text = label.text().split(":")
                label_text[0] = parsed_lifts[i]
                label.setText(": ".join(label_text))

            for i, label in enumerate(lifts_for_reps_labels):
                label_text = label.text().split(":")
                label_text[0] = parsed_lifts[i]
                label.setText(": ".join(label_text))

            self.refresh_graph(True)

    @pyqtSlot(bool)
    def changed_1RM_lifts(self, changed):
        if changed:
            fetch_weight = list(
                json.loads(
                    self.db_wrapper.fetch_local_column(
                        self.table_name, "one_rep_maxes")).values())
            self.set_1RM_labels_text(fetch_weight)

    @pyqtSlot(bool)
    def changed_lifts_for_reps(self, changed):
        if changed:
            fetch_reps_and_weight = list(
                json.loads(
                    self.db_wrapper.fetch_local_column(
                        self.table_name, "lifts_for_reps")).values())
            self.set_lifts_for_reps_labels_text(fetch_reps_and_weight)

    def set_lifts_for_reps_labels_text(self, text):
        lifts_for_reps_labels = [
            self.horizontal_press_label_reps, self.floor_pull_label_reps,
            self.squat_label_reps, self.vertical_press_label_reps
        ]

        for i, label in enumerate(lifts_for_reps_labels):
            label_text = label.text().split(": ")
            label_text[1] = " ".join(["x".join(text[i]), self.units])
            label.setText(": ".join(label_text))

    def set_1RM_labels_text(self, text):
        one_RM_labels = [
            self.horizontal_press_label_ORM, self.floor_pull_label_ORM,
            self.squat_label_ORM, self.vertical_press_label_ORM
        ]
        for i, label in enumerate(one_RM_labels):
            label_text = label.text().split(": ")
            label_text[1] = " ".join([text[i], self.units])
            label.setText(": ".join(label_text))

    def clear_one_rep_maxes(self):
        for exercise, value in self.one_rep_maxes.items():
            self.one_rep_maxes[exercise] = "0"
        self.db_wrapper.update_table_column(self.table_name, "one_rep_maxes",
                                            self.one_rep_maxes)
        self.set_1RM_labels_text(list(self.one_rep_maxes.values()))
        self.update_1RM_window.set_line_edit_values()

    def clear_lifts_for_reps(self):
        lifts_for_reps = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "lifts_for_reps"))
        for exercise in lifts_for_reps:
            lifts_for_reps[exercise] = ["0", "0"]
        self.db_wrapper.update_table_column(self.table_name, "lifts_for_reps",
                                            lifts_for_reps)
        self.set_lifts_for_reps_labels_text(list(lifts_for_reps.values()))
        self.lifts_for_reps.set_line_edit_values()

    def replace_graph(self, lift_type):
        new_graph = OneRMGraphCanvas(lift_type, self.rm_history,
                                     self.current_year, self)
        new_toolbar = NavigationToolbar(new_graph, self)
        new_toolbar.setStyleSheet("background-color: white;")

        old_toolbar_reference = self.graph_layout.itemAt(0).widget()
        old_graph_reference = self.graph_layout.itemAt(1).widget()

        self.graph_layout.replaceWidget(old_toolbar_reference, new_toolbar)
        self.graph_layout.replaceWidget(old_graph_reference, new_graph)

        old_toolbar_reference.deleteLater()
        old_graph_reference.deleteLater()

    def change_exercise_graph(self, exercise_name):
        lift_type = None
        for l_type, exercise in self.preferred_lifts.items():
            if exercise == exercise_name: lift_type = l_type
        self.replace_graph(lift_type)

    def change_graph_year(self, year):
        self.current_year = year
        lift_type = None
        for l_type, exercise in self.preferred_lifts.items():
            if exercise == str(self.lifts_combobox.currentText()):
                lift_type = l_type
        self.replace_graph(lift_type)
        self.change_year_combobox.setCurrentText(self.current_year)

    @pyqtSlot(bool)
    def refresh_graph(self, signal):
        if signal:
            self.rm_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "rm_history"))
            lift_type = None
            for l_type, exercise in self.preferred_lifts.items():
                if exercise == str(self.lifts_combobox.currentText()):
                    lift_type = l_type
            self.replace_graph(lift_type)

    def convert_lift_history_weight(self, convert_to_units):
        try:
            lift_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "lift_history"))
        except TypeError:  # lift history is empty
            return
        if convert_to_units == "kg":
            for lift in lift_history:
                if isinstance(
                        lift[1], list
                ):  # second element of history entry is list, it is lifts_for_reps entry
                    lift[1][1] = str(pounds_to_kg(float(lift[1][1])))
                else:
                    lift[1] = str(pounds_to_kg(float(lift[1])))
        elif convert_to_units == "lb":
            for lift in lift_history:
                if isinstance(lift[1], list):
                    lift[1][1] = str(kg_to_pounds(float(lift[1][1])))
                else:
                    lift[1] = str(kg_to_pounds(float(lift[1])))
        lift_history = json.dumps(lift_history)
        self.db_wrapper.update_table_column(self.table_name,
                                            "lift_history",
                                            lift_history,
                                            convert_lift_history_units=True)

    def add_year_to_rm_history(self, year):
        new_year = {}
        for month in self.db_wrapper.months:
            exercises_dict = {}
            for lift_type in self.preferred_lifts:
                exercises_dict[lift_type] = {
                    self.preferred_lifts[lift_type]: []
                }
            new_year[month] = exercises_dict
        self.rm_history[str(year)] = new_year
        self.rm_history = json.dumps(self.rm_history)
        self.db_wrapper.update_table_column(self.table_name, "rm_history",
                                            self.rm_history)
Exemple #16
0
class Win(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(Win, self).__init__(*args, **kwargs)

        cont = QWidget()
        self.setCentralWidget(cont)

        self.lay = QVBoxLayout()
        cont.setLayout(self.lay)

        self.le = QLineEdit()
        self.lay.addWidget(self.le)

        self.le.returnPressed.connect(self.loadCommand)

        self.tree = TreeView()
        self.table = QTableView()

        self.name = ''
        self.data = None
        self.lay.addWidget(self.tree)

        menu = self.menuBar().addMenu('Options')
        self.isTable = menu.addAction('Table')
        self.isTable.setCheckable(True)
        self.isTable.setShortcut('Alt+T')
        self.isTable.changed.connect(self.reloadModel)

    def clearModels(self):
        self.tree.setModel(None)
        self.table.setModel(None)

    def reloadModel(self):
        table = self.isTable.isChecked()

        if table:
            table = (isinstance(self.data, list) and all(
                isinstance(obj, dict)
                for obj in self.data)) or (isinstance(self.data, dict) and all(
                    isinstance(obj, list) for obj in self.data.values()))

        self.clearModels()
        if table:
            self.table.setModel(ObjTable(self.data))
            self.table.resizeColumnsToContents()
            self.table.setSortingEnabled(True)
            self.lay.replaceWidget(self.tree, self.table)
        else:
            self.tree.setModel(ObjConverter(self.data, name=self.name))
            self.tree.expandAll()
            self.lay.replaceWidget(self.table, self.tree)

        self.table.setVisible(table)
        self.tree.setVisible(not table)

    def loadCommand(self):
        text = self.le.text()
        if os.path.isfile(text):
            with open(text) as fd:
                obj = loadJson(fd.read())
        else:
            try:
                out = subprocess.check_output(text, shell=True).decode('utf-8')
            except subprocess.CalledProcessError as e:
                obj = str(e)
            else:
                try:
                    obj = loadJson(out)
                except ValueError as e:
                    try:
                        obj = loadJson('[%s]' %
                                       ','.join(out.strip().split('\n')))
                    except ValueError:
                        obj = str(e)

        self.setData(obj, text)

    def setFile(self, f):
        self.le.setText(f)

    def setData(self, obj, name=''):
        self.data = obj
        self.name = name
        self.reloadModel()
Exemple #17
0
class SectionEditor(QWidget):
    sectionEditorCopied = pyqtSignal(object)

    def __init__(self, fullwidth):
        QWidget.__init__(self)
        from widgets.hyperlink import HyperLink
        from widgets.flatbutton import FlatButton
        from widgets.section import Section
        from widgets.content import ContentType
        from widgets.elementeditor import ElementEditor, Mode

        self.fullwidth = fullwidth
        self.section = None
        self.id = None
        self.cssclass = None
        self.style = None
        self.attributes = None
        self.setAutoFillBackground(True)
        self.setAcceptDrops(True)
        self.setBGColor()
        vbox = QVBoxLayout()
        vbox.setAlignment(Qt.AlignTop)
        vbox.setSpacing(5)
        self.edit_button = FlatButton(":/images/edit_normal.png",
                                      ":/images/edit_hover.png")
        self.copy_button = FlatButton(":/images/copy_normal.png",
                                      ":/images/copy_hover.png")
        self.delete_button = FlatButton(":/images/trash_normal.png",
                                        ":/images/trash_hover.png")
        self.edit_button.setToolTip("Edit Section")
        self.delete_button.setToolTip("Delete Section")
        self.copy_button.setToolTip("Copy Section")
        self.edit_button.setMaximumWidth(24)
        self.copy_button.setMaximumWidth(24)
        self.delete_button.setMaximumWidth(24)
        vbox.addWidget(self.edit_button)
        vbox.addWidget(self.copy_button)
        vbox.addWidget(self.delete_button)

        vboxRight = QVBoxLayout()
        vboxRight.setAlignment(Qt.AlignLeft)
        layout = QHBoxLayout()
        self.layout = QVBoxLayout()
        layout.addLayout(vbox)
        addRow = HyperLink("(+) Add Row")
        vboxRight.addLayout(self.layout)

        if self.fullwidth:
            ee = ElementEditor()
            ee.elementEnabled.connect(self.addElement)
            ee.elementDragged.connect(self.addElement)

            # connect(ee, SIGNAL(elementCopied(ElementEditor*)), self, SLOT(copyElement(ElementEditor*)))

            self.layout.addWidget(ee, 0, Qt.AlignTop)
        else:
            vboxRight.addWidget(addRow)
        layout.addLayout(vboxRight)
        self.setLayout(layout)

        self.delete_button.clicked.connect(self.delete)
        self.copy_button.clicked.connect(self.copy)
        addRow.clicked.connect(self.addRow)
        self.edit_button.clicked.connect(self.edit)

    def edit(self):
        ce = self.getContentEditor()
        if ce:
            ce.sectionEdit(self)

    def addRow(self):
        row = Row()
        self.section._items.append(row)
        re = RowEditor()
        re.load(row)
        self.addRowEditor(re)
        ce = self.getContentEditor()
        if ce:
            ce.editChanged("Add Row")

    def addRowEditor(self, re):
        re.rowEditorCopied.connect(self.copyRowEditor)
        self.layout.addWidget(re)

    def copyRowEditor(self, re):
        ren = RowEditor()
        row = re.row.clone()
        ren.load(row)
        self.section._items.append(row)
        self.addRowEditor(ren)
        ce = self.getContentEditor()
        if ce:
            ce.editChanged("Copy Row")

    def copy(self):
        self.sectionEditorCopied.emit(self)

    def delete(self):
        pe = self.parentWidget()
        if pe:
            pe.removeSection(self)

    def setBGColor(self):
        pal = self.palette()
        if self.fullwidth:
            pal.setColor(QPalette.Background, QColor("#800080"))
        else:
            pal.setColor(QPalette.Background,
                         QColor(self.palette().base().color().name()))
        self.setPalette(pal)

    def addElement(self):
        ee = ElementEditor()
        self.layout.addWidget(ee, 0, Qt.AlignTop)
        ee.elementEnabled.connect(self.addElement)
        ee.elementDragged.connect(self.addElement)
        # connect(ee, SIGNAL(elementCopied(ElementEditor*)), self, SLOT(copyElement(ElementEditor*)))

    def addElementEditor(self, ee):
        ee.elementEnabled.connect(self.addElement)
        ee.elementDragged.connect(self.addElement)

        # connect(ee, SIGNAL(elementCopied(ElementEditor*)), self, SLOT(copyElement(ElementEditor*)))
        self.layout.insertWidget(self.layout.count() - 1, ee, 0, Qt.AlignTop)

    def setSection(self, section):
        self.section = section

    def removeRowEditor(self, re):
        re.setVisible(False)
        self.layout.removeWidget(re)

    def load(self, section):
        from widgets.elementeditor import ElementEditor, Mode
        from widgets.roweditor import RowEditor

        self.section = section
        for item in self.section.items:
            if isinstance(item, Row):
                re = RowEditor()
                re.load(item)
                self.addRowEditor(re)
            else:
                ee = ElementEditor()
                ee.setContent(item)
                ee.setMode(Mode.ENABLED)
                self.addElementEditor(ee)

    def getContentEditor(self):
        pe = self.parentWidget()
        if pe:
            sa = pe.parentWidget()
            if sa:
                vp = sa.parentWidget()
                if vp:
                    cee = vp.parentWidget()
                    if cee:
                        return cee

        return None

    def dragEnterEvent(self, event):
        myData = event.mimeData()
        if myData:
            if not self.section.fullwidth and isinstance(
                    myData.getData(), RowEditor):
                # insert a dropzone at the end
                self.layout.addWidget(DropZone(myData.width, myData.height))
                event.accept()
            elif self.section.fullwidth and isinstance(myData.getData(),
                                                       ElementEditor):
                for i in range(self.layout.count()):
                    editor = self.layout.itemAt(i).widget()
                    if editor and editor.mode == Mode.EMPTY:
                        editor.setMode(Mode.DROPZONE)
                        break
                event.accept()
            else:
                event.ignore()
        else:
            event.ignore()

    def dragLeaveEvent(self, event):
        # remove dropzones
        for i in range(self.layout.count()):
            dz = self.layout.itemAt(i).widget()
            if isinstance(dz, DropZone):
                dz.hide()
                self.layout.removeWidget(dz)
                del dz
                break

            editor = self.layout.itemAt(i).widget()
            if isinstance(editor,
                          ElementEditor) and editor.mode == Mode.DROPZONE:
                # put editor to the end of the list
                editor.setMode(Mode.EMPTY)
                self.layout.removeWidget(editor)
                self.layout.addWidget(editor)
                break
        event.accept()

    def dragMoveEvent(self, event):
        myData = event.mimeData()
        if myData:
            re = myData.getData()
            if isinstance(re, RowEditor):
                height = 0
                row = 0

                # evaluate position for the dropzone to be placed
                for i in range(self.layout.count()):
                    editor = self.layout.itemAt(i).widget()
                    if isinstance(editor, RowEditor):
                        if event.pos().y() > height and event.pos().y(
                        ) < height + editor.height():
                            break
                        height += editor.height()
                        row = row + 1

                # find dropzone and replace it to location
                for i in range(self.layout.count()):
                    dz = self.layout.itemAt(i).widget()
                    if isinstance(dz, DropZone):
                        if i != row:
                            self.layout.insertWidget(row, dz)
                        break

                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                ee = myData.getData()
                if ee:
                    row = event.pos().y() / 50
                    for i in range(self.layout.count()):
                        editor = self.layout.itemAt(i).widget()
                        if editor and editor.mode == Mode.DROPZONE:
                            if i != row:
                                # put dropzone under mouse pointer
                                self.layout.insertWidget(row, editor)
                            break
                    event.setDropAction(Qt.MoveAction)
                    event.accept()
                else:
                    event.ignore()
        else:
            event.ignore()

    def dropEvent(self, event):
        myData = event.mimeData()
        if myData:
            re = myData.getData()
            if isinstance(re, RowEditor):
                # place the dragged RowEditor to the place where DropZone is now
                for i in range(self.layout.count()):
                    dz = self.layout.itemAt(i).widget()
                    if isinstance(dz, DropZone):
                        dz.hide()
                        self.layout.replaceWidget(dz, re)
                        new_pos = i
                        re.show()
                        del dz
                        break

                ce = self.getContentEditor()
                if ce:
                    myData.source_list.remove(re.row)
                    self.section.insertElement(re.row, new_pos)
                    ce.editChanged("Move Row")
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                ee = myData.getData()
                if isinstance(ee, ElementEditor):
                    for i in range(self.layout.count()):
                        dz = self.layout.itemAt(i).widget()
                        if isinstance(
                                dz,
                                ElementEditor) and dz.mode == Mode.DROPZONE:
                            # remove widget if it belongs to self layout
                            self.layout.removeWidget(ee)

                            # replace dropzone with dragged element
                            self.layout.replaceWidget(dz, ee)
                            new_pos = i
                            # and put dropzone to the end of the list
                            dz.setMode(Mode.EMPTY)
                            self.layout.removeWidget(dz)
                            self.layout.addWidget(dz)
                            break
                    ee.dropped()
                    ee.show()
                    ee.elementEnabled.disconnect()
                    ee.elementDragged.disconnect()
                    # ee.elementCopied.disconnect()
                    ee.elementEnabled.connect(self.addElement)
                    ee.elementDragged.connect(self.addElement)
                    # ee.elementCopied.connect(self.copyElement)

                    ce = self.getContentEditor()
                    if ce:
                        myData.source_list.remove(ee.content)
                        self.section.insertElement(ee.content, new_pos)
                        ce.editChanged("Move Element")
                    event.setDropAction(Qt.MoveAction)
                    event.accept()
                else:
                    event.ignore()
        else:
            event.ignore()

    def enableColumnAcceptDrop(self, mode):
        for i in range(self.layout.count()):
            re = self.layout.itemAt(i).widget()
            if isinstance(re, RowEditor):
                re.enableColumnAcceptDrop(mode)

    def mousePressEvent(self, event):
        mimeData = WidgetMimeData()
        mimeData.setSize(self.size().width(), self.size().height())
        mimeData.setData(self)

        pixmap = QPixmap(self.size())
        self.render(pixmap)

        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(event.pos())
        drag.setPixmap(pixmap)

        pe = self.parentWidget()
        pe.removeSectionEditor(self)
        pe.enableColumnAcceptDrop(False)
        pe.enableSectionAcceptDrop(False)
        self.hide()

        if drag.exec(Qt.MoveAction) == Qt.IgnoreAction:
            pe.addSection(self)
            self.show()

        pe.enableColumnAcceptDrop(True)
        pe.enableSectionAcceptDrop(True)

    def removeElement(self, content):
        self.section._items.remove(content)
Exemple #18
0
class SkillsetsOverTime(QWidget):
	def __init__(self, stats: backend.XmlStats, link_group: LinkGroup):
		super().__init__()
		self._stats = stats
		self._acc_rating_over_time: Optional[Any] = None # Will be calculated on-demand
		self._link_group = link_group

		self._layout = QVBoxLayout()
		self.setLayout(self._layout)

		self._plot = QWidget() # This dummy will be replaced by setup function later
		self._layout.addWidget(self._plot)

		bottom_pane = QWidget()
		sub_layout = QHBoxLayout()
		bottom_pane.setLayout(sub_layout)
		self._layout.addWidget(bottom_pane)

		self._cursor_pos_span = QLabel()
		self._cursor_pos_span.setWordWrap(True)
		sub_layout.addWidget(self._cursor_pos_span)

		sub_layout.addWidget(vertical_separator())

		display_options = QComboBox()
		display_options.addItem("Show all scores")
		display_options.addItem("Show AAA-/AAAA-only")
		display_options.currentIndexChanged.connect(self._current_index_changed)
		sub_layout.addWidget(display_options)

		self._current_index_changed(0) # Trigger first render

	def _current_index_changed(self, index: int):
		if index == 0:
			new_plot = self._setup_skillsets()
		elif index == 1:
			new_plot = self._setup_acc_rating()
		else:
			print(f"Warning: unknown dropdown index {index}. Ignoring")
			return
		
		self._layout.replaceWidget(self._plot, new_plot)
		self._plot = new_plot
		self._layout.invalidate() # Causes glitches otherwise

	def _crosshair_moved_skillsets(self, cursor_x: datetime) -> None:
		rating = find_rating_at(cursor_x, self._stats.skillsets_over_time) or [0, 0, 0, 0, 0, 0, 0, 0]

		text = f"{cursor_x.date()}: "
		for i in range(8):
			color = globals.SKILLSET_COLORS_8[i]
			name = globals.SKILLSET_NAMES_8[i]
			text_color = globals.SKILLSET_CONTRASTING_TEXT_COLORS_8[i]
			text += f'<span style="background-color:#{color}; color:#{text_color}">{name}: <b>{rating[i]:.2f}</b> </span>'
		
		self._cursor_pos_span.setText(text)
	
	def _setup_skillsets(self) -> PlotWrapper:
		plot_items = []
		for i in range(8):
			plot_items.append(PlotItem(
				data=LinePlotItem(points=[(dt, rating[i]) for dt, rating in self._stats.skillsets_over_time]),
				color=globals.SKILLSET_COLORS_8[i],
				legend_name=globals.SKILLSET_NAMES_8[i],
			))
		# Make overall line thick
		plot_items[0].data.width *= 3 # type: ignore
		
		return PlotWrapper(
			item=plot_items,
			title="Skillsets over time",
			datetime_x_axis=True,
			show_x_crosshair=True,
			crosshair_move_callback=self._crosshair_moved_skillsets,
			link_group=self._link_group,
		)
	
	def _crosshair_moved_acc(self, cursor_x: datetime) -> None:
		if not self._acc_rating_over_time:
			print("Warning: acc_rating_over_time not set in mouse move handler; skipping")
			return

		normal_rating = find_rating_at(cursor_x, self._acc_rating_over_time.normal) or 0.0
		aaa_rating = find_rating_at(cursor_x, self._acc_rating_over_time.aaa) or 0.0
		aaaa_rating = find_rating_at(cursor_x, self._acc_rating_over_time.aaaa) or 0.0

		text = f"{cursor_x.date()}: " +\
			f'<span style="background-color:#{ALL_GRADES_COLOR}; color:#000000">All: <b>{normal_rating:.2f}</b> </span>' +\
			f'<span style="background-color:#{globals.AAA_COLOR}; color:#000000">AAA: <b>{aaa_rating:.2f}</b> </span>' +\
			f'<span style="background-color:#{globals.AAAA_COLOR}; color:#000000">AAAA: <b>{aaaa_rating:.2f}</b> </span>'
		
		self._cursor_pos_span.setText(text)

	def _setup_acc_rating(self) -> PlotWrapper:
		if not self._acc_rating_over_time:
			self._acc_rating_over_time = blocking_loading_bar(
				lambda *args: backend.calculate_acc_rating_over_time(self._stats, *args),
				"Calculating accuracy ratings",
			)
		
		def make_plot_item(ratings: List[Tuple[date, float]], color: str, name: str) -> PlotItem:
			return PlotItem(
				data=LinePlotItem(
					points=ratings,
					width=3, # we have 3 distinct lines, might as well make them thicc
				),
				color=color,
				legend_name=name,
			)
		
		return PlotWrapper(
			item=[
				make_plot_item(self._acc_rating_over_time.normal, ALL_GRADES_COLOR, "All scores"),
				make_plot_item(self._acc_rating_over_time.aaa, globals.AAA_COLOR, "Only AAA"),
				make_plot_item(self._acc_rating_over_time.aaaa, globals.AAAA_COLOR, "Only AAAA"),
			],
			title="Skillsets over time",
			datetime_x_axis=True,
			show_x_crosshair=True,
			crosshair_move_callback=self._crosshair_moved_acc,
			link_group=self._link_group,
		)
Exemple #19
0
class Display(QWidget):
    def __init__(self, parent=None):
        super(Display, self).__init__(parent)

        self.setWindowTitle("Perudo Online")

        # We have to keep a reference to `Client` as it is a QThread
        self.client = Client()
        self.client.connection_made.connect(self.update_connection_status)
        self.client.name_allowed.connect(self.confirm_name_allowed)
        self.client.lobby_joined.connect(self.populate_lobby_layout)
        self.client.lobby_update_info.connect(self.update_lobby_layout)

        self.menu_layout = self.create_menu_layout()
        self.name_layout = self.create_enter_name_layout()
        #self.game_layout = self.create_other_player_layout("North")
        stacked_layout = QStackedLayout(self)
        stacked_layout.addWidget(self.menu_layout)
        stacked_layout.addWidget(self.name_layout)
        #stacked_layout.addWidget(self.lobby_layout)
        #stacked_layout.addWidget(self.game_layout)

        self.setLayout(stacked_layout)

        self.client.start()

    def create_menu_layout(self):
        menu_layout = QVBoxLayout()

        self.connection_status = QLabel("No Connection")
        menu_layout.addWidget(self.connection_status)
        self.start_button = QPushButton("New Game")
        menu_layout.addWidget(self.start_button)
        quit_button = QPushButton("Quit")
        menu_layout.addWidget(quit_button)

        self.start_button.setEnabled(False)
        self.start_button.clicked.connect(self.start_game)
        quit_button.clicked.connect(self.quit)
        frame = QFrame()
        frame.setLayout(menu_layout)
        return frame

    def create_enter_name_layout(self):
        layout = QVBoxLayout()

        text = QLabel("Enter your name:")
        layout.addWidget(text)
        self.name_input = QLineEdit()
        layout.addWidget(self.name_input)
        self.name_enter_button = QPushButton("Enter")
        layout.addWidget(self.name_enter_button)
        self.name_allowed_label = QLabel()
        layout.addWidget(self.name_allowed_label)

        self.name_enter_button.clicked.connect(self.enter_name)

        frame = QFrame()
        frame.setLayout(layout)
        return frame

    def create_lobby_layout(self):
        print("Creating lobby layout")
        # Name lobby id and time left on left, all players on right
        layout = QHBoxLayout()

        # Left
        left_layout = QVBoxLayout()
        name_label = QLabel("-")
        left_layout.addWidget(name_label)
        self.lobby_id_label = QLabel("-")
        left_layout.addWidget(self.lobby_id_label)
        self.time_left = QLabel("Time Left: -")
        left_layout.addWidget(self.time_left)

        layout.addLayout(left_layout)

        # Right
        right_frame = QFrame()
        self.names_list_layout = QVBoxLayout()
        self.name_labels = []
        for i in range(MAX_PLAYERS):
            label = QLabel("[placeholder]")
            self.name_labels.append(label)
            self.names_list_layout.addWidget(label)
        right_frame.setLayout(self.names_list_layout)

        layout.addWidget(right_frame)

        frame = QFrame()
        frame.setLayout(layout)
        return frame

    def populate_lobby_layout(self, lobby_id, initial_names):
        # Called once when the initial lobby data is sent from the server
        self.lobby_id_label.setText(lobby_id)

    def update_lobby_layout(self, time_left, name_list):
        # Called each time an update is received from the server
        print(f"Updating lobby layout {time_left}, {name_list}")
        ##self.time_left_id.setText(f"Time Left: {time_left}")
        new_name_labels = []
        for i in range(len(self.name_labels)):
            label = QLabel(name_list[i])
            new_name_labels.append(label)
            self.names_list_layout.replaceWidget(self.name_labels[i],
                                                 new_name_labels[i])
        self.name_labels = new_name_labels

    def create_play_layout(self, player_names):
        play_layout = QGridLayout

    def create_other_player_layout(self, name):
        # Creates a dice mat, a cup, a name label and the place to write what
        # bids the player made
        layout = QVBoxLayout()
        player_name = QLabel(name)

        scroll = QScrollArea()
        scroll.setMaximumHeight(90)
        scroll.setWidgetResizable(True)  # CRITICAL

        inner = QFrame(scroll)
        inner.setLayout(QVBoxLayout())

        scroll.setWidget(inner)  # CRITICAL

        for i in range(50):
            inner.layout().addWidget(QLabel(f"{i} threes"))

        layout.addWidget(player_name)
        layout.addWidget(scroll)

        frame = QFrame()
        frame.setLayout(layout)
        return frame

    def enter_name(self):
        print(f"Starting game with name {self.name_input.text()}")
        self.name_enter_button.setDisabled(True)
        self.client.set_nickname(self.name_input.text())

    def confirm_name_allowed(self, name_valid):
        if name_valid:
            self.lobby_layout = self.create_lobby_layout()
            self.layout().addWidget(self.lobby_layout)
            self.layout().setCurrentIndex(2)
            self.name_allowed_label.setText("")
        else:
            self.name_allowed_label.setText("Name already taken")
        self.name_enter_button.setEnabled(True)

    def start_game(self):
        self.layout().setCurrentIndex(1)

    def set_up(self):
        print("Creating window...")
        print("[Enter name here:]")
        print("[Start Game] (Disabled)")
        print("[Quit]")

    def quit(self):
        print("Closing window...")
        QApplication.quit()

    def update_connection_status(self, status):
        self.connected = status
        if self.connected:
            print("We have a connection, can click on [Start Game] now")
            self.connection_status.setText("Connected")
            self.start_button.setEnabled(True)

        else:
            print("We have lost connection")
            self.connection_status.setText("No Connection")
            self.start_button.setEnabled(False)

    def get_menu_input(self):
        # Return whether any buttons have been pressed
        rand = random()
        if rand > 0.99:
            print("Clicked on 'start'")
            return "start"
        #elif rand < 0.01:
        #	print("Clicked on 'quit'")
        #	return "quit"
        else:
            return None

    def get_name(self):
        # Returns what was in the entry box
        #name = choice(["Oin", "Gloin", "Gimli", "Thorin", "Ori",
        #					  "Nori", "Dori", "Fili", "Kili", "Bifur", "Bofur",
        #					  "Bombur", "Balin", "Dwalin"])
        name = choice(["Oin", "Gloin", "Ori"])
        return name

    def load_lobby(self):
        print("Displaying lobby...")
        print("No lobby joined yet")

    def ask_for_new_name(self):
        print("You need to input a different name")

    def get_new_name(self):
        # Merge with get_name()?
        name = choice([
            "Oin", "Gloin", "Gimli", "Thorin", "Ori", "Nori", "Dori", "Fili",
            "Kili", "Bifur", "Bofur", "Bombur", "Balin", "Dwalin"
        ])
        return name

    def join_lobby(self, init_names):
        print("Joined lobby with players {} already in".format(init_names))

    def update_lobby(self, time_left, player_name_list, starting_soon):
        print("{} seconds left".format(time_left))
        print("{} players in lobby".format(player_name_list))
        if starting_soon:
            print("Starting game soon")

    def load_game(self, player_name_list):
        print("Loading game screen with player {}".format(player_name_list))

    def start_round(self, dice_list, dice_quantities):
        print("Resetting round: \nYour dice: {}\nOther dice:".format(
            dice_list, dice_quantities))
class VariantInfoWidget(QWidget):
    """Creates a simple about dialog.

    The about dialog contains general information about the application and
    shows the copyright notice.
    That's why the class has no attributes or return values.

    """
    legendChanged = pyqtSignal()

    def __init__(self):
        super().__init__()

        self.setMinimumWidth(220)
        self._OXYGEN_PATH_22 = os.path.join("resources", "icons", "oxygen", "22")

        self.model = None
        self.curves = []

        self.results = QWidget()

        # main layout
        self.layout = QVBoxLayout(self)
        #self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.results)

        self.showResults()

    def setModel(self, model):
        self.model = model
        self.model.dataChanged.connect(self.update)
        #self.model.modelReset.connect(self.update)
        self.model.modelReset.connect(self.clear)

        # das muss optimiert werden, weil dies private Signale sind
        # es dient dazu, dass gelöschte, oder veränderte (verschobene) Zeilen
        # nicht mehr ausgewählt werden können (selectionModel)
        #self.model.rowsRemoved.connect(self.clear)
        #self.model.rowsMoved.connect(self.clear)

        #self.model.calculated.connect(self.calculate)

    def clear(self):
        self.curves.clear()
        self.showResults()

    def updateResults(self, index):
        self.curves.append(index)

    def updateColor(self, index, color):
        self.model.setData(index, color.name(), TreeModel.ColorRole)
        self.legendChanged.emit()

    def showResults(self):
        new = QWidget()
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        # title label of the results area
        self.titleLabel = QLabel("<b>" + QApplication.translate("VariantInfoWidget", "Legend and result(s)") + ":</b>")
        layout.addWidget(self.titleLabel)

        if self.curves:
            # headline
            description = QLabel(QApplication.translate("VariantInfoWidget", "Break even line for"))
            layout.addSpacing(10)
            layout.addWidget(description)

            # show legend for all plotted curves
            for curve in self.curves:
                layout.addSpacing(6)
                vertical = QHBoxLayout()
                vertical.setContentsMargins(0, 0, 0, 0)
                line = ColorLine(curve)
                line.farbeDef = curve.data(TreeModel.ColorRole)
                line.colorChanged.connect(self.updateColor)


                vertical.addWidget(line)
                vertical.addSpacing(10)
                vertical.addWidget(QLabel(
                    curve.parent().data(TreeModel.IdentificationRole) +
                    " " + QApplication.translate("VariantInfoWidget", "and") + " " +
                    curve.data(TreeModel.IdentificationRole)))
                layout.addLayout(vertical)
                result = QHBoxLayout()
                result.setContentsMargins(0, 0, 0, 0)
                result.addSpacing(35)

                # check, if the plant count is smaller than the calculation
                point = curve.data(TreeModel.ResultRole) * self.model.projectData("length")

                resultText = QApplication.translate("VariantInfoWidget", "The costs are equal")
                if self.model.projectData("count") < point:
                    resultText = QApplication.translate("VariantInfoWidget", "Tree shelter is profitable")
                elif self.model.projectData("count") > point:
                    resultText = QApplication.translate("VariantInfoWidget", "Fence is profitable")

                result.addWidget(QLabel("<i>" + resultText + "</i>"))
                layout.addLayout(result)

            # show the color hint
            layout.addSpacing(10)
            layout.addWidget(QLabel("(" + QApplication.translate("VariantInfoWidget", "to change the color click on the symbol") + ")", wordWrap=True))

            layout.addSpacing(10)
            helpSymbol = QLabel(pixmap=QPixmap(os.path.join(self._OXYGEN_PATH_22, "system-help.png")))
            helpText = ClickableLabel("<a href='#'>" + QApplication.translate("VariantInfoWidget", "Explanation of calculation") + "</a>")
            helpText.clicked.connect(self.showHelp)
            helpLayout = QHBoxLayout()
            helpLayout.setContentsMargins(0, 0, 0, 0)
            helpLayout.setSpacing(8)
            helpLayout.addWidget(helpSymbol, alignment=Qt.AlignVCenter)
            helpLayout.addWidget(helpText, alignment=Qt.AlignVCenter)
            helpLayout.addStretch()
            layout.addLayout(helpLayout)

            # add hints
            separator = QFrame(frameShadow=QFrame.Sunken, frameShape=QFrame.HLine)

            # not the best solution but it works
            # this is very tricky!
            hintTitle = QLabel("<b>" + QApplication.translate("VariantInfoWidget", "Relevant information:") + "</b>")
            hintArrow = QLabel("<ul style='list-style-type: square; margin-left: -25px;'>" +
                    "<li>" + QApplication.translate("VariantInfoWidget", "the orange arrow displays the result of the calculation") + "</li></ul>", wordWrap=True)                # orangener Pfeil zeigt das Ergebnis der Kalkulation
            hintLines = QLabel("<ul style='list-style-type: square; margin-left: -25px;'>" +
                    "<li>" + QApplication.translate("VariantInfoWidget", "the auxiliary lines for fence length and number of plants are moveable") + "</li></ul>", wordWrap=True)             # Hilfslinien für Zaunlänge und Pflanzenzahl sind beweglich

            layout.addSpacing(30)
            layout.addWidget(separator)
            layout.addWidget(hintTitle)
            layout.addSpacing(10)
            layout.addWidget(hintArrow)
            layout.addSpacing(6)
            layout.addWidget(hintLines)
            layout.addStretch()
        else:
            # no curve was plotted
            # there is no result available
            layout.addSpacing(10)
            layout.addWidget(QLabel(QApplication.translate("VariantInfoWidget", "No results available!")))
            layout.addStretch()

        new.setLayout(layout)

        self.layout.replaceWidget(self.results, new)
        self.results.deleteLater()
        self.results = new

    def showHelp(self):
        # create the documentation path with
        # the current locale settings
        docFile = os.path.join("doc", "documentation_" +
                self.locale().name()[:2] + ".pdf")

        # on every platfrom a different
        # start operation is needed
        if sys.platform == "win32":
            os.startfile(docFile)
        elif sys.platform == "darwin":
            subprocess.call(("open", docFile))
        elif sys.platform.startswith("linux"):
            subprocess.call(("xdg-open", docFile))
Exemple #21
0
class InternalsPanel(Panel, QAttribute, qattributes={Toolbox: False}):
    """A Panel displaying system internals.
    May be of interest during development.

    Attributes
    ----------
    _modules: dict
        A mapping from module names to module information.
        This can be the acutal module (if already loaded),
        or a string describing the state of the module
        ("not loaddd" or "not found"). This information
        is initialized and updated by the method
        :py:meth:_updateModules.

    _moduleName: str = None

    Graphical elements
    ------------------
    _grid: QGridLayout
    _moduleGrid: QGridLayout = None
    """
    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self._modules = {}
        self._moduleName = None

        self.initUI()

    def initUI(self):
        self._layout = QVBoxLayout()
        self._grid = QGridLayout()
        self._grid.addWidget(self.modulesInfo(), 0, 0)
        self._grid.addLayout(self.systemInfo(), 0, 1)

        self._layout.addLayout(self._grid)
        self._info = QLabel("Info")
        self._layout.addWidget(self._info)

        self._processInfo = QProcessInfo()
        self.addAttributePropagation(Toolbox, self._processInfo)
        self._layout.addWidget(self._processInfo)

        self.setLayout(self._layout)

    #@QtCore.pyqtSlot()
    @protect
    def _onInfo(self, checked: bool = False):
        sender = self.sender()
        print(sender, type(sender), sender.text())
        resource = Resource[sender.ID]
        self.showInfo(ModuleInfo(resource=resource))

    #@QtCore.pyqtSlot()
    @protect
    def _onUpdateModules(self, checked: bool = False) -> None:
        self._updateModules()

    def showInfo(self, info: QWidget):
        """Show a new info widget.

        Arguments
        ---------
        info: QWidget
           The widget to be displayed in the info region of the
           panel. This will replace the previously displayed
           info widget.
        """
        if self._layout.replaceWidget(self._info, info) is not None:
            self._info.deleteLater()
            self._info = info

    def modulesInfo(self) -> QGroupBox:
        """Create a QGridLayout with two columns displaying module
        information. The first column contains the module name, the
        second column version (if loaded) or availability.
        Modules are listed in the order given by :py:meth:modules.

        Returns
        ------
        box: QGroupBox
            A QWidget displaying the module information.
        """
        box = QGroupBox('Modules')
        box.setMinimumWidth(300)

        self._moduleGrid = QGridLayout()
        self._moduleGrid.addWidget(QLabel("<b>Package</b>", self), 0, 0)
        self._moduleGrid.addWidget(QLabel("<b>Version</b>", self), 0, 1)

        for i, m in enumerate(ModuleResource):
            button = QPushButton(m.label, self)
            button.ID = m._id  # FIXME[hack]
            button.setFlat(True)
            button.clicked.connect(self._onInfo)
            self._moduleGrid.addWidget(button, 1 + i, 0)
            self._moduleGrid.addWidget(QLabel('', self), 1 + i, 1)
        self._updateModules()

        boxLayout = QVBoxLayout()
        boxLayout.addLayout(self._moduleGrid)

        updateButton = QPushButton("Update")
        updateButton.clicked.connect(self._onUpdateModules)
        boxLayout.addWidget(updateButton)
        boxLayout.addStretch()
        box.setLayout(boxLayout)

        return box

    def _updateModules(self):
        """Update the module list.
        """
        for i, m in enumerate(ModuleResource):
            if m.prepared:
                info = m.version
            elif m.available:
                info = "not loaded"
            else:
                info = "not found"
            self._moduleGrid.itemAtPosition(1 + i, 1).widget().setText(info)

    def systemInfo(self):

        pythonBox = QGroupBox('Python')
        boxLayout = QVBoxLayout()
        boxLayout.addWidget(QLabel(f"Python version: {sys.version}"))
        boxLayout.addWidget(QLabel(f"Platform: {sys.platform}"))
        boxLayout.addWidget(QLabel(f"Prefix: {sys.prefix}"))
        boxLayout.addWidget(QLabel(f"Executable: {sys.executable}"))
        boxLayout.addStretch()
        pythonBox.setLayout(boxLayout)

        hardwareBox = QGroupBox('Hardware')
        boxLayout = QVBoxLayout()
        for i, cpu in enumerate(cpus):
            prefix = f"{i+1}. " if len(cpus) > 1 else ""
            boxLayout.addWidget(QLabel(f"{prefix}CPU: {cpu.name}"))
        for i, gpu in enumerate(gpus):
            prefix = f"{i+1}. " if len(gpus) > 1 else ""
            boxLayout.addWidget(QLabel(f"{prefix}GPU: {gpu.name}"))
        # Memory (1)
        import os
        mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
        # SC_PAGE_SIZE is often 4096.
        # SC_PAGESIZE and SC_PAGE_SIZE are equal.
        mem = mem_bytes >> 20
        boxLayout.addWidget(
            QLabel("Total physical memory: {:,} MiB".format(mem)))
        boxLayout.addStretch()
        hardwareBox.setLayout(boxLayout)

        #
        # Platform
        #
        systemBox = QGroupBox('System')
        boxLayout = QVBoxLayout()

        import platform
        boxLayout.addWidget(QLabel(f"node: {platform.node()}"))
        # boxLayout.addWidget(QLabel(f"uname: {platform.uname()}"))
        boxLayout.addWidget(QLabel(f"system: {platform.system()}"))
        boxLayout.addWidget(QLabel(f"release: {platform.release()}"))
        # boxLayout.addWidget(QLabel(f"version: {platform.version()}"))
        boxLayout.addWidget(
            QLabel(f"machine/processor: "
                   f"{platform.machine()}/"
                   f"{platform.processor()}"))
        boxLayout.addStretch()
        systemBox.setLayout(boxLayout)

        resourcesBox = QGroupBox('Resources')
        boxLayout = QVBoxLayout()

        # Memory (2)
        # a useful solution that works for various operating systems,
        # including Linux, Windows 7, etc.:
        try:
            import psutil
            mem = psutil.virtual_memory()
            # mem.total: total physical memory available
            boxLayout.addWidget(
                QLabel("Total physical memory: "
                       f"{mem.total}"))
            process = psutil.Process(os.getpid())
            boxLayout.addWidget(
                QLabel("Memory usage: "
                       f"{process.memory_info().rss}"))
        except ModuleNotFoundError:
            pass

        # For Unixes (Linux, Mac OS X, Solaris) you could also use the
        # getrusage() function from the standard library module
        # resource. The resulting object has the attribute ru_maxrss,
        # which gives peak memory usage for the calling process.

        # resource is a standard library module.
        import resource

        # The Python docs aren't clear on what the units are exactly,
        # but the Mac OS X man page for getrusage(2) describes the
        # units as bytes. The Linux man page isn't clear, but it seems
        # to be equivalent to the information from /proc/self/status,
        # which is in kilobytes.
        rusage = resource.getrusage(resource.RUSAGE_SELF)
        boxLayout.addWidget(
            QLabel("Peak Memory usage: {:,} kiB".format(rusage.ru_maxrss)))

        if cuda is not None:
            button = QPushButton("CUDA")
            #button.setFlat(True)
            @protect
            def slot(clicked: bool):
                self.showInfo(self.cudaInfo())

            button.clicked.connect(slot)
            boxLayout.addWidget(button)

        resourcesBox.setLayout(boxLayout)

        #
        # layout the boxes
        #
        layout = QVBoxLayout()
        row = QHBoxLayout()
        row.addWidget(hardwareBox)
        row.addWidget(pythonBox)
        row.addWidget(systemBox)
        layout.addLayout(row)
        layout.addWidget(resourcesBox)
        layout.addStretch()
        return layout

    def cv2Info(self, cv2):
        layout = QVBoxLayout()

        info = cv2.getBuildInformation()

        text = QPlainTextEdit()
        fixedFont = QFontDatabase.systemFont(QFontDatabase.FixedFont)
        text.document().setDefaultFont(fixedFont)
        text.setReadOnly(True)
        text.setPlainText(info)

        layout.addWidget(QLabel(f"Version: {cv2.__version__}"))
        layout.addWidget(QLabel(f"Library: {cv2.__file__}"))
        layout.addWidget(text)
        layout.addStretch()
        return layout

    def tensorflowInfo(self, tf):
        layout = QVBoxLayout()
        label = QLabel("<b>Tensorflow<b>\n" f"Version = {tf.__version__}")
        layout.addWidget(label)

        layout.addWidget(QLabel(f"Tensorflow devices:"))
        #  There is an undocumented method called
        #  device_lib.list_local_devices() that enables you to list
        #  the devices available in the local process (As an
        #  undocumented method, this is subject to backwards
        #  incompatible changes.)
        from tensorflow.python.client import device_lib
        local_device_protos = device_lib.list_local_devices()
        for dev in local_device_protos:
            layout.addWidget(QLabel(f"Device: {dev.name} ({dev.device_type})"))

        # Note that (at least up to TensorFlow 1.4), calling
        # device_lib.list_local_devices() will run some initialization
        # code that, by default, will allocate all of the GPU memory
        # on all of the devices (GitHub issue). To avoid this, first
        # create a session with an explicitly small
        # per_process_gpu_fraction, or allow_growth=True, to prevent
        # all of the memory being allocated. See this question for
        # more details

        # https://stackoverflow.com/questions/38009682/how-to-tell-if-tensorflow-is-using-gpu-acceleration-from-inside-python-shell
        layout.addStretch()
        return layout

    def kerasInfo(self, keras):
        layout = QVBoxLayout()
        layout.addWidget(QLabel(f"Backend: {keras.backend.backend()}"))
        layout.addStretch()
        return layout

    def cudaInfo(self):
        cudaBox = QGroupBox('CUDA')
        boxLayout = QVBoxLayout()

        if os.path.exists('/proc/driver/nvidia/version'):
            with open('/proc/driver/nvidia/version') as f:
                driver_info = f.read()
            match = re.search('Kernel Module +([^ ]*)', driver_info)
            if match:
                boxLayout.addWidget(QLabel(f"Kernel module: {match.group(1)}"))
            match = re.search('gcc version +([^ ]*)', driver_info)
            if match:
                boxLayout.addWidget(QLabel(f"GCC version: {match.group(1)}"))

            boxLayout.addWidget(
                QLabel(f"NVIDIA Kernel driver: "
                       f"{cuda.driver_version}"))
            boxLayout.addWidget(
                QLabel(f"CUDA Toolkit version: "
                       f"{cuda.toolkit_version}"))

            text = QPlainTextEdit()
            fixedFont = QFontDatabase.systemFont(QFontDatabase.FixedFont)
            text.document().setDefaultFont(fixedFont)
            text.setReadOnly(True)
            text.setPlainText(str(cuda.nvidia_smi))
            text.appendPlainText(str(cuda.nvidia_smi_l))
            boxLayout.addWidget(text)

        # Now use the python module pycuda
        try:
            import pycuda.autoinit
            import pycuda.driver as cuda

            (free, total) = cuda.mem_get_info()
            boxLayout.addWidget(QLabel("<b>Global GPU Memory</b>"))
            boxLayout.addWidget(QLabel(f"Total: {total}"))
            boxLayout.addWidget(QLabel(f"Free: {free}"))
            boxLayout.addWidget(
                QLabel("Global memory occupancy: "
                       f"{free*100/total:2.4}% free"))

            for devicenum in range(cuda.Device.count()):
                device = cuda.Device(devicenum)
                attrs = device.get_attributes()

                # Beyond this point is just pretty printing
                print("\n===Attributes for device %d" % devicenum)
                for (key, value) in attrs.items():
                    print("%s:%s" % (str(key), str(value)))
        except ImportError as e:
            print(e, file=sys.stderr)
            # ImportError: libcurand.so.8.0
            # The problem occurs with the current anaconda version
            # (2017.1, "conda install -c lukepfister pycuda").
            # The dynamic library "_driver.cpython-36m-x86_64-linux-gnu.so"
            # is linked against "libcurand.so.8.0". However, the cudatookit
            # installed by anaconda is verion 9.0.
            boxLayout.addWidget(
                QLabel("Python CUDA module (pycuda) not availabe"))

        try:
            nvmlInfo = QNvmlInfo()
            boxLayout.addWidget(nvmlInfo)
            add_timer_callback(nvmlInfo.update)
        except ImportError as e:
            print(e, file=sys.stderr)
            boxLayout.addWidget(
                QLabel("Python NVML module (py3nvml) not availabe"))

        cudaBox.setLayout(boxLayout)
        return cudaBox
Exemple #22
0
class MainUi(QtWidgets.QMainWindow, Ui_MainWindow):
    # 这里的第一个变量是你该窗口的类型,第二个是该窗口对象。
    # 这里是主窗口类型。所以设置成当QtWidgets.QMainWindow。
    # 你的窗口是一个会话框时你需要设置成:QtWidgets.QDialog
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.initFrame()

    def initFrame(self):
        self.layout = QVBoxLayout(self.frame)
        self.layout.setContentsMargins(0, 0, 0, 0)
        # index = self.comboBox.currentIndex()
        self.pic = MyMplCanvas(self.frame,
                               index=0,
                               loc='0,0',
                               width=80,
                               height=4,
                               dpi=100)
        self.layout.addWidget(self.pic)

    def show_instruction(self):
        self.textBrowser.show()


#         self.textBrowser.setText(
#             """可视化AP数据库使用说明:
# 1.选择指定数据库
# 2.选择要使用的功能
#             """)

    def open_ap_list(self):
        file_name, file_type = QtWidgets.QFileDialog.getOpenFileName(
            self, "请选择SQLite文件", path, "DataBase (*.db)")  # 设置文件扩展名过滤,用;间隔
        # 注意用双分号间隔
        if len(file_name) == 0:
            return
        file_name = file_name.replace('/', "\\")  # windows下需要进行文件分隔符转换
        connection = sq.connect(file_name)
        cursor = connection.cursor()
        select = cursor.execute('select Name, Mac from main.ap_table_id ')
        for row in select:
            ap_list.append(row[0])
            mac_list.append(row[1])
        if len(ap_list) > 0:
            QtWidgets.QMessageBox.information(
                self,  # 使用infomation信息框
                "说明",
                "加载成功",
                QtWidgets.QMessageBox.Ok)
        self.tableWidgetAp.setHorizontalHeaderLabels(['Name',
                                                      'Mac'])  # 设置表格表头数据
        self.tableWidgetAp.setColumnCount(4)  # 设置表格的列数
        self.tableWidgetAp.setRowCount(len(ap_list) / 2 + 1)  # 设置表格的行数
        self.tableWidgetAp.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeToContents)  # 表格设置成大小随内容改变
        self.tableWidgetAp.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)  # 表格设置成只读
        self.tableWidgetAp.setAlternatingRowColors(True)  # 隔行改变颜色
        self.tableWidgetAp.clear()  # 表格清空,不清空的话会永远残留
        for i in range(len(ap_list)):
            if i % 2 == 0:
                self.tableWidgetAp.setItem(
                    i / 2, 0,
                    QTableWidgetItem(ap_list[i]))  # 设置表格内容为字符串"content"
                self.tableWidgetAp.setItem(
                    i / 2, 1,
                    QTableWidgetItem(mac_list[i]))  # 设置表格内容为字符串"content"
            else:
                self.tableWidgetAp.setItem(
                    i / 2, 2,
                    QTableWidgetItem(ap_list[i]))  # 设置表格内容为字符串"content"
                self.tableWidgetAp.setItem(
                    i / 2, 3,
                    QTableWidgetItem(mac_list[i]))  # 设置表格内容为字符串"content"
            self.comboBox.insertItem(i, ap_list[i])
        self.textBrowser.hide()

    def open_database(self):
        if len(ap_list) < 1:
            QtWidgets.QMessageBox.information(
                self,  # 使用infomation信息框
                "ERROR",
                "未读取到AP表单",
                QtWidgets.QMessageBox.Ok)
        file_name, file_type = QtWidgets.QFileDialog.getOpenFileName(
            self, "请选择SQLite文件", path, "DataBase (*.db)")  # 设置文件扩展名过滤,用;间隔
        if len(file_name) == 0:
            return
        file_name = file_name.replace('/', "\\")  # windows下需要进行文件分隔符转换
        connection = sq.connect(file_name)
        cursor = connection.cursor()
        select = cursor.execute('select * from main.wifi_table ')
        lastX = -1
        lastY = -1
        for row in select:
            data_list = []
            x = row[1]
            y = row[2]
            key = '%d,%d' % (x, y)
            for i in range(3, 3 + len(ap_list)):
                data_list.append(row[i])
            if lastX == x and lastY == y:
                data_dict[key] += [data_list]
            elif key in data_dict.keys():
                data_dict[key] += [data_list]
            else:
                data_dict[key] = [data_list]
            lastX = x
            lastY = y

        if len(data_dict) > 0:
            QtWidgets.QMessageBox.information(
                self,  # 使用infomation信息框
                "说明",
                "加载成功",
                QtWidgets.QMessageBox.Ok)
        COL_PER_PAGE = 10
        self.tableWidgetLoc.setColumnCount(COL_PER_PAGE)  # 设置表格的列数
        self.tableWidgetLoc.setRowCount(
            int(len(data_dict) / COL_PER_PAGE) + 1)  # 设置表格的行数
        self.tableWidgetLoc.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeToContents)  # 表格设置成大小随内容改变
        self.tableWidgetLoc.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)  # 表格设置成只读
        self.tableWidgetLoc.setAlternatingRowColors(True)  # 隔行改变颜色
        self.tableWidgetLoc.clear()  # 表格清空,不清空的话会永远残留
        col = 0
        row = 0
        for key in data_dict.keys():
            loc_list = key.split(',')
            x = int(loc_list[0])
            y = int(loc_list[1])
            self.tableWidgetLoc.setItem(
                row, col,
                QTableWidgetItem("%d,%d" % (x, y)))  # 设置表格内容为字符串"content"
            col += 1
            if col / COL_PER_PAGE > 1:
                col %= COL_PER_PAGE
                row += 1

    def show_time(self):
        x = self.spinBoxX.text()
        y = self.spinBoxY.text()
        loc = '%s,%s' % (x, y)
        if loc == '0,0':
            pass
        elif x != 0 and y != 0 and loc in data_dict.keys():
            pass
        else:
            QtWidgets.QMessageBox.information(
                self,  # 使用infomation信息框
                "ERROR",
                "不存在的数据",
                QtWidgets.QMessageBox.Ok)
            return
        index = self.comboBox.currentIndex()
        newPic = UpdateMplCanvas(self.frame,
                                 index,
                                 loc,
                                 width=80,
                                 height=4,
                                 dpi=100)
        self.layout.replaceWidget(self.pic, newPic)
        self.pic = newPic