Пример #1
0
 def setCurrentIndex(self, index):
     """Change the current widget being displayed with an animation."""
     old_widget = self.currentWidget()
     new_widget = self.widget(index)
     if old_widget != new_widget:
         self.fader_widget = ui_tools.FaderWidget(self.currentWidget(),
                                                  self.widget(index))
     QStackedWidget.setCurrentIndex(self, index)
Пример #2
0
 def setCurrentIndex(self, index):
     """Change the current widget being displayed with an animation."""
     old_widget = self.currentWidget()
     new_widget = self.widget(index)
     if old_widget != new_widget:
         self.fader_widget = ui_tools.FaderWidget(self.currentWidget(),
                                                  self.widget(index))
     QStackedWidget.setCurrentIndex(self, index)
Пример #3
0
class SettingsPanel(QDialog):
    def __init__(self, plugin_manager, settings_manager, parent=None):
        super().__init__(parent)
        self.settings_manager = settings_manager
        self.plugin_manager = plugin_manager
        self.contents_widget = QListWidget()
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setMaximumWidth(105)
        self.contents_widget.setSpacing(12)

        self.pages_widget = QStackedWidget()
        self.pages_widget.addWidget(EnvironmentPage(self.settings_manager))
        self.pages_widget.addWidget(
            PluginsPage(self.settings_manager, self.plugin_manager))

        close_button = QPushButton("Close")
        update_button = QPushButton("Update")

        self.__create_icons()
        self.contents_widget.setCurrentRow(0)

        close_button.clicked.connect(self.close)
        update_button.clicked.connect(
            lambda: self.pages_widget.currentWidget().update_settings())

        horizontal_layout = QHBoxLayout()
        horizontal_layout.addWidget(self.contents_widget)
        horizontal_layout.addWidget(self.pages_widget, 1)

        buttons_layout = QHBoxLayout()
        buttons_layout.addStretch(1)
        buttons_layout.addWidget(update_button)
        buttons_layout.addWidget(close_button)

        main_layout = QVBoxLayout()
        main_layout.addLayout(horizontal_layout)
        main_layout.addStretch(1)
        main_layout.addSpacing(12)
        main_layout.addLayout(buttons_layout)

        self.setLayout(main_layout)
        self.setWindowTitle("Settings Panel")

    def change_page(self, current, previous):
        if not current:
            current = previous
        self.pages_widget.setCurrentIndex(self.contents_widget.row(current))

    def __create_icons(self):
        environment_button = QListWidgetItem(self.contents_widget)
        environment_button.setText("Environment")
        environment_button.setTextAlignment(Qt.AlignHCenter)
        environment_button.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        plugins_button = QListWidgetItem(self.contents_widget)
        plugins_button.setText("Plugins")
        plugins_button.setTextAlignment(Qt.AlignCenter)
        plugins_button.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.contents_widget.currentItemChanged.connect(self.change_page)
Пример #4
0
    def animationDoneSlot(self):
        """Animation end processing function"""
        # Since the setCurrentIndex method is rewritten, the method of the parent class itself is used here.
#         self.setCurrentIndex(self._next)
        QStackedWidget.setCurrentIndex(self, self._next)
        w = self.widget(self._now)
        w.hide()
        w.move(self._pnow)
        self._active = 0
Пример #5
0
class StackedExample(QWidget):
    def __init__(self):
        super(StackedExample, self).__init__()
        self.leftlist = QListWidget()
        self.leftlist.insertItem(0, 'Contact')
        self.leftlist.insertItem(1, 'Personal')
        self.leftlist.insertItem(2, 'Educational')

        self.stack1 = QWidget()
        self.stack2 = QWidget()
        self.stack3 = QWidget()

        self.stack1UI()
        self.stack2UI()
        self.stack3UI()

        self.Stack = QStackedWidget(self)
        self.Stack.addWidget(self.stack1)
        self.Stack.addWidget(self.stack2)
        self.Stack.addWidget(self.stack3)

        hbox = QHBoxLayout(self)
        hbox.addWidget(self.leftlist)
        hbox.addWidget(self.Stack)

        self.setLayout(hbox)
        self.leftlist.currentRowChanged.connect(self.display)
        self.setGeometry(300, 50, 10, 10)
        self.setWindowTitle('StackedWidget demo')
        self.show()

    def stack1UI(self):
        layout = QFormLayout()
        layout.addRow("Name", QLineEdit())
        layout.addRow("Address", QLineEdit())
        #self.setTabText(0,"Contact Details")
        self.stack1.setLayout(layout)

    def stack2UI(self):
        layout = QFormLayout()
        sex = QHBoxLayout()
        sex.addWidget(QRadioButton("Male"))
        sex.addWidget(QRadioButton("Female"))
        layout.addRow(QLabel("Sex"), sex)
        layout.addRow("Date of Birth", QLineEdit())

        self.stack2.setLayout(layout)

    def stack3UI(self):
        layout = QHBoxLayout()
        layout.addWidget(QLabel("subjects"))
        layout.addWidget(QCheckBox("Physics"))
        layout.addWidget(QCheckBox("Maths"))
        self.stack3.setLayout(layout)

    def display(self, idx):
        self.Stack.setCurrentIndex(idx)
 def animationDoneSlot(self):
     """动画结束处理函数"""
     # 由于重写了setCurrentIndex方法所以这里要用父类本身的方法
     #         self.setCurrentIndex(self._next)
     QStackedWidget.setCurrentIndex(self, self._next)
     w = self.widget(self._now)
     w.hide()
     w.move(self._pnow)
     self._active = 0
Пример #7
0
class CMainWindows(QWidget):
    def __init__(self):
        super(CMainWindows, self).__init__()
        self.InitView()

    def InitView(self):
        from trunk import entity

        self.setFixedSize(960, 800)
        self.SetCenter()
        self.setFixedSize(self.width(), self.height())
        self.setWindowTitle("神武3工具箱")
        self.setWindowIcon(QIcon("trunk/images/title_red.png"))

        self.m_MainLayout = QHBoxLayout(self)  # 新建一个水平布局作为本窗体的主布局
        self.m_MainLayout.setSpacing(10)  # 设置主布局内边距以及控件间距为10px

        self.m_ComBoxLayout = QVBoxLayout()  # 新建垂直子布局用于放置按键
        self.m_ComBoxLayout.setContentsMargins(10, 10, 10,
                                               10)  # 设置此子布局和内部控件的间距为10px

        oLabel = QLabel(self)
        oLabel.setText("当前操作:")
        oLabel.setFixedHeight(20)
        self.m_ComBoxLayout.addWidget(oLabel)

        self.m_ComBox = QComboBox(self)

        for oEntry in entity.get_all_eneity():
            self.m_ComBox.addItem(oEntry.m_Name)
        self.m_ComBox.currentIndexChanged.connect(self.OnComBoxChange)
        self.m_ComBox.setFixedWidth(self.m_ComBox.width() + 10)

        self.m_ComBoxLayout.addWidget(self.m_ComBox)

        oSplitter = QSplitter(self)  # 占位符
        self.m_ComBoxLayout.addWidget(oSplitter)

        self.m_StackedWidget = QStackedWidget(self)
        for oEntry in entity.get_all_eneity():
            self.m_StackedWidget.addWidget(oEntry)

        self.m_MainLayout.addLayout(self.m_ComBoxLayout)  # 将子布局加入主布局
        self.m_MainLayout.addWidget(self.m_StackedWidget)

    def OnComBoxChange(self):
        self.m_StackedWidget.setCurrentIndex(self.m_ComBox.currentIndex())

    def SetSize(self, iHeight, iWidth):
        self.resize(iHeight, iWidth)

    def SetCenter(self):  # 主窗口居中显示函数
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
Пример #8
0
class CentralWidget(QWidget):
    """
	Making a class from the QWidget class, specify variables and behavior 

	Variables:
		mainLayout <QVBoxLayout>
		nameAndDateLayout <QHBoxLayout>
		interactionLayout <QVBoxLayout>
		attributeInventoryLayout <QHBoxLayout>
		attributeLayout <QVBoxLayout>
		comboBoxesFormLayout <QFormLayout>
		nameLabel <QLabel>
		dateTimeLabel <QLabel>
		difficultyLabel <QLabel>
		strengthLabel <QLabel>
		dexterifyLabel <QLabel>
		constitutionLabel <QLabel>
		intellectLabel <QLabel>
		inventoryLabel <QLabel>
		nameLineEdit <QLineEdit>
		classSelectorComboBox <QComboBox>
		difficultyComboBox <QComboBox>
		finishPushButton <QPushButton>

	Methods:
		classChange
		difficultyChange
		finishChange
		nameChange
		
	"""
    def __init__(self):

        super().__init__()

        self.Stack = QStackedWidget(self)
        self.characterCreateWidget = CharacterCreateWidget()
        self.baseGraphicWorldTileWidget = BaseGraphicWorldTileWidget()

        self.characterCreateWidget.procGame.connect(self.change_index)
        self.characterCreateWidget.procCharLabel.connect(
            self.baseGraphicWorldTileWidget.set_player_image)
        self.characterCreateWidget.procRoomDescription.connect(
            self.baseGraphicWorldTileWidget.set_room_description)
        self.characterCreateWidget.procRoomAvailableAction.connect(
            self.baseGraphicWorldTileWidget.set_actions)
        self.baseGraphicWorldTileWidget.procGameChange.connect(
            self.characterCreateWidget.userInputChange)

        self.Stack.addWidget(self.characterCreateWidget)
        self.Stack.addWidget(self.baseGraphicWorldTileWidget)

    def change_index(self, index):
        self.Stack.setCurrentIndex(index)
Пример #9
0
class SettingsDialog(QWidget):
    """
    Settings dialog opened from File -> Settings...
    """
    def __init__(self, config, parent=None):
        super(SettingsDialog, self).__init__(parent)
        self.config = config

        # Widgets
        self.console = ConsoleSettings(self.config)

        # Settings
        self.widget_connections = {
            "Console": self.console
        }

        # Settings Tree
        self.settings_tree = QTreeWidget()
        self.settings_tree.setColumnCount(2)
        self.settings_tree.header().hideSection(1)
        self.settings_tree.header().close()

        # Settings Stacked Widget
        self.stack = QStackedWidget()
        self.populate = Populate(self, display=self.stack)
        self.populate.tree_widget(
            self.settings_tree.invisibleRootItem(),
            self.widget_connections
        )

        # Layouts
        self.tree_layout = QVBoxLayout()
        self.tree_layout.addWidget(self.settings_tree)

        self.horizontal_layout = QHBoxLayout()
        self.horizontal_layout.addLayout(self.tree_layout)
        self.horizontal_layout.addWidget(self.stack)

        self.setLayout(self.horizontal_layout)

        # Slots
        self.settings_tree.currentItemChanged.connect(self.display)

    def display(self, current):
        """
        Show the corresponding widget for the selected tree item.

        :param current: the current tree item
        """
        try:
            item_connection = int(current.text(1))
            self.stack.setCurrentIndex(item_connection)
        except ValueError as _:
            pass
Пример #10
0
class Editor(QDialog):
    """Basic scene editor."""
    def __init__(self, parent: MainWindow, renderers: List[Renderer]) -> None:
        """Initialize the Editor."""
        super().__init__(parent=parent)
        self.renderers = renderers

        self.tree_widget = QTreeWidget()
        self.tree_widget.setHeaderHidden(True)
        self.stacked_widget = QStackedWidget()
        self.layout = QHBoxLayout()
        self.layout.addWidget(self.tree_widget)
        self.layout.addWidget(self.stacked_widget)

        def _selection_callback() -> None:
            for item in self.tree_widget.selectedItems():
                widget_idx = item.data(0, Qt.ItemDataRole.UserRole)
                self.stacked_widget.setCurrentIndex(widget_idx)

        self.tree_widget.itemSelectionChanged.connect(_selection_callback)

        self.setLayout(self.layout)
        self.setWindowTitle("Editor")
        self.setModal(True)

        self.update()

    def update(self) -> None:
        """Update the internal widget list."""
        self.tree_widget.clear()
        for idx, renderer in enumerate(self.renderers):
            actors = renderer._actors  # pylint: disable=protected-access
            widget_idx = self.stacked_widget.addWidget(
                _get_renderer_widget(renderer))
            top_item = QTreeWidgetItem(self.tree_widget,
                                       ["Renderer {}".format(idx)])
            top_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx)
            self.tree_widget.addTopLevelItem(top_item)
            for name, actor in actors.items():
                if actor is not None:
                    widget_idx = self.stacked_widget.addWidget(
                        _get_actor_widget(actor))
                    child_item = QTreeWidgetItem(top_item, [name])
                    child_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx)
                    top_item.addChild(child_item)
        self.tree_widget.expandAll()

    def toggle(self) -> None:
        """Toggle the editor visibility."""
        self.update()
        if self.isVisible():
            self.hide()
        else:
            self.show()
Пример #11
0
class MainApp(QMainWindow):
    def __init__(self):
        super(MainApp, self).__init__()
        # App metadata
        self.setWindowTitle('Alice Installer')
        self.setWindowIcon(QIcon(PATH + '/images/icon.png'))
        self.setWindowFlags(Qt.WindowCloseButtonHint)
        self.setFixedSize(800, 400)

        self.load_fonts()

        # Set central widget and init ui
        self.central_widget = QWidget(self)
        self.central_widget.resize(self.frameSize())
        self.initUI()

    def initUI(self):
        self.stacked_widget = QStackedWidget(self.central_widget)
        self.stacked_widget.resize(self.frameSize())
        self.stacked_widget.setAutoFillBackground(False)
        self.stacked_widget.setStyleSheet('background-color: #111118;')

        # Import activities and add to stack
        self.start_app = StartApp(self)
        self.install_window = InstallWindow(self)
        self.install_complete = InstallComplete(self)

        self.stacked_widget.addWidget(self.start_app)
        self.stacked_widget.addWidget(self.install_window)
        self.stacked_widget.addWidget(self.install_complete)

        # Activities Triggers
        self.start_app.install.clicked.connect(lambda: self.switch_layout(1))

    def load_fonts(self, path=PATH + '/fonts/'):
        fonts = [f for f in listdir(path) if isfile(join(path, f))]

        self.font_db = {}

        # For each font finded in /fonts add to Application and create a directory of fonts
        for font in fonts:
            self.font_id = QFontDatabase.addApplicationFont(path + font)
            self.font_db[font.replace("-", " ")[:-4]] = self.font_id

    def set_font(self, font_name, font_size):
        selected_font = QFontDatabase.applicationFontFamilies(
            self.font_db[font_name])
        font = QFont()
        font.setFamily(selected_font[0])
        font.setPointSize(int(font_size))
        return font

    def switch_layout(self, index):
        self.stacked_widget.setCurrentIndex(index)
Пример #12
0
class Window(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.Stack = QStackedWidget()

        self.menu_frm = menu.MenuWidget(self.prep_widgets)
        self.workspace = None
        self.settings = None

        self.Stack.addWidget(self.menu_frm)

        self.setCentralWidget(self.Stack)
        self.render()
        self.showMaximized()

        self.setStyleSheet(open('app.css').read())

    def prep_widgets(self):

        self.workspace = workstation.App_Form()
        self.settings = settings.App_Form()
        self.Stack.addWidget(self.workspace)
        self.Stack.addWidget(self.settings)

        fn_pack = function_pack(self.render)

        self.workspace.set_fn_pack(fn_pack)
        self.settings.set_fn_pack(fn_pack)

        fn_pack.render_workspace()

    def render(self, i=0):

        self.Stack.setCurrentIndex(i)

        # if you switch to the workspace
        # refresh the workspace widget
        if i == 1:
            self.workspace.display()
        # if you switch back to the meny
        # refresh the menu widget
        if i == 0:
            # Except I don't know how to refresh the menu widget without taking it of the stack widget
            controller.TbWorkspace.log_off()
            # Need to refresh the workspaces, and settings
            if (self.workspace or self.settings):
                self.workspace.setParent(None)
                self.settings.setParent(None)

    def set_workspace(self, widget):
        self.workspace = widget

    def set_settings(self, widget):
        self.settings = widget
Пример #13
0
class Cherry(QMainWindow, Ui_MainWindow):
    """ Main window that holds the main layout """
    def __init__(self, parent=None):
        super().__init__()

        self.setupUi(self)

        # Create sidebar
        self.sidebar = SidebarWidget(self.centralwidget)
        self.sidebar.actionChanged.connect(self.changeDisplay)

        self.stackedWidget = QStackedWidget()

        # Create separate widgets (views) for stacked widget
        self.configWidget = ConfigWidget(self.stackedWidget)
        self.configWidget.configCancelled.connect(self.changeDisplayToHome)
        self.configWidget.configChanged.connect(self.changeConfigInHome)

        self.homeWidget = HomeWidget(self.stackedWidget)
        self.homeWidget.setConfig(self.configWidget.getConfig())

        self.progressWidget = ProgressWidget(self.stackedWidget)
        self.historyWidget = HistoryWidget(self.stackedWidget)

        self.stackedWidget.addWidget(self.homeWidget)
        self.stackedWidget.addWidget(self.progressWidget)
        self.stackedWidget.addWidget(self.historyWidget)
        self.stackedWidget.addWidget(self.configWidget)

        self.horizontalLayout.addWidget(self.sidebar)
        self.horizontalLayout.addWidget(self.stackedWidget)

        # Apparently not needed anymore
        #self.setMinimumWidth(self.stackedWidget.width() + self.sidebar.width() + 10)

        self.windowIcon = QIcon(":/icons/cherry.png")
        self.setWindowIcon(self.windowIcon)
        self.setWindowTitle("cherry-dl")

    @pyqtSlot(int)
    def changeDisplay(self, index):
        self.stackedWidget.setCurrentIndex(index)

    @pyqtSlot()
    def changeDisplayToHome(self):
        self.stackedWidget.setCurrentIndex(0)

    @pyqtSlot()
    def changeConfigInHome(self):
        self.homeWidget.setConfig(self.configWidget.getConfig())

    def closeEvent(self, closeEvent):
        QCoreApplication.exit()
Пример #14
0
class TicTacToeWindow(QWidget):
    def __init__(self, boardlist, current_board, amplist):
        super(TicTacToeWindow, self).__init__()
        self.setWindowTitle("Quantum Tic Tac Toe")
        self.BoardPage = QVBoxLayout(self)
        self.data = QHBoxLayout(self)
        self.BoardPage.addLayout(self.data)

        self.stack = QStackedWidget(self)
        self.leftlist = QListWidget()
        self.data.addWidget(self.leftlist)
        self.data.addWidget(self.stack)
        for i in range(len(boardlist)):
            self.leftlist.insertItem(i, boardlist[i])
            self.stackUI(boardlist[i], amplist[i])

        buttonlayout = QHBoxLayout()
        button_play = QPushButton('Move')
        button_play.clicked.connect(self.move)
        buttonlayout.addWidget(button_play)
        self.BoardPage.addLayout(buttonlayout)
        self.setLayout(self.BoardPage)

        self.leftlist.currentRowChanged.connect(self.display)

    def stackUI(self, board, amp):
        s = QWidget()
        amplist = [
            '0', '1', '-1', 'i', '-i', '1/np.sqrt(2)', '-1/np.sqrt(2)',
            'i/np.sqrt(2)', '-i/np.sqrt(2)'
        ]
        vBox = QVBoxLayout(self)
        amplitude = QLabel(amp)
        Tictactoelayout = QGridLayout()
        for i in range(3):
            for j in range(3):
                index = (i * 3) + j
                if board[index] == '0':
                    ampcb = QComboBox()
                    ampcb.addItems(amplist)
                    Tictactoelayout.addWidget(ampcb, i, j)
                else:
                    Tictactoelayout.addWidget(QLabel(board[index]), i, j)
        vBox.addWidget(amplitude)
        vBox.addLayout(Tictactoelayout)
        s.setLayout(vBox)
        self.stack.addWidget(s)

    def move(self):
        print("move")

    def display(self, i):
        self.stack.setCurrentIndex(i)
Пример #15
0
class ConfigDialog(QDialog):
    def __init__(self, parent=None):
        super(ConfigDialog, self).__init__(parent)
        self.contentsWidget = QListWidget()
        self.contentsWidget.setViewMode(QListView.IconMode)
        self.contentsWidget.setIconSize(QSize(96, 84))
        self.contentsWidget.setMovement(QListView.Static)
        self.contentsWidget.setMaximumWidth(128)
        self.contentsWidget.setSpacing(12)
        self.pagesWidget = QStackedWidget()
        self.pagesWidget.addWidget(ConfigurationPage())
        self.pagesWidget.addWidget(UpdatePage())
        self.pagesWidget.addWidget(QueryPage())
        closeButton = QPushButton("Close")
        self.createIcons()
        self.contentsWidget.setCurrentRow(0)
        closeButton.clicked.connect(self.close)
        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.contentsWidget)
        horizontalLayout.addWidget(self.pagesWidget, 1)
        buttonsLayout = QHBoxLayout()
        buttonsLayout.addStretch(1)
        buttonsLayout.addWidget(closeButton)
        mainLayout = QVBoxLayout()
        mainLayout.addLayout(horizontalLayout)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(12)
        mainLayout.addLayout(buttonsLayout)
        self.setLayout(mainLayout)
        self.setWindowTitle("Config Dialog")

    def changePage(self, current, previous):
        if not current:
            current = previous
        self.pagesWidget.setCurrentIndex(self.contentsWidget.row(current))

    def createIcons(self):
        configButton = QListWidgetItem(self.contentsWidget)
        configButton.setIcon(QIcon(':/images/config.png'))
        configButton.setText("Configuration")
        configButton.setTextAlignment(Qt.AlignHCenter)
        configButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        updateButton = QListWidgetItem(self.contentsWidget)
        updateButton.setIcon(QIcon(':/images/update.png'))
        updateButton.setText("Update")
        updateButton.setTextAlignment(Qt.AlignHCenter)
        updateButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        queryButton = QListWidgetItem(self.contentsWidget)
        queryButton.setIcon(QIcon(':/images/query.png'))
        queryButton.setText("Query")
        queryButton.setTextAlignment(Qt.AlignHCenter)
        queryButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.contentsWidget.currentItemChanged.connect(self.changePage)
Пример #16
0
class MainWindow(QMainWindow):
    quit = pyqtSignal()

    def __init__(
            self,
            parent=None,
            flags=Qt.WindowFlags(),
    ):
        super().__init__(parent, flags)

        self.setWindowTitle("Photobooth")

        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)

    def set_widgets(
        self,
        idle_widget: IdleWidget,
        preview_widget: PreviewWidget,
        printing_widget: PrintingWidget,
        error_widget: ErrorWidget,
    ):

        self.central_widget.addWidget(idle_widget)
        self.central_widget.addWidget(preview_widget)
        self.central_widget.addWidget(printing_widget)
        self.central_widget.addWidget(error_widget)

    def select_idle(self):
        self._select_by_index(0)

    def select_preview(self):
        self._select_by_index(1)

    def select_printing(self):
        self._select_by_index(2)

    def select_error(self):
        self._select_by_index(3)

    def keyPressEvent(self, event: QEvent):
        key = event.key()
        logger.info("keyPressEvent: %s", key)

        if key in [Qt.Key_Q]:
            event.accept()
            self.quit.emit()
        else:
            event.ignore()

    def _select_by_index(self, index):
        self.central_widget.setCurrentIndex(index)
Пример #17
0
class TabLayout(QGridLayout):
    """The QT layout that displays tabs."""
    def __init__(self, window: "OctogonWindow"):
        super().__init__()

        self.setContentsMargins(QMargins(0, 0, 0, 0))
        self.setSpacing(0)

        self.btn_scoreboard = QPushButton("scoreboard", parent=window)
        self.btn_scoreboard.clicked.connect(lambda: self.set_tab(0))
        self.btn_overlays = QPushButton("overlays", parent=window)
        self.btn_overlays.clicked.connect(lambda: self.set_tab(1))

        # the pages
        self.widget_scoreboard = QWidget(window)
        self.widget_scoreboard.setLayout(ScoreboardLayout(window))
        self.widget_overlays = QWidget(window)
        self.widget_overlays.setLayout(OverlaysLayout(window))

        # the stackedlayout containing the pages
        self.widget_stack = QStackedWidget(window)
        self.widget_stack.addWidget(self.widget_scoreboard)
        self.widget_stack.addWidget(self.widget_overlays)

        self.addWidget(self.btn_scoreboard, 0, 0)
        self.addWidget(self.btn_overlays, 0, 1)

        self.addWidget(self.widget_stack, 1, 0, 1, 2)

        self.set_tab(0)

    def set_tab(self, n: int):

        # print("tab changed")
        IGNORE, EXPAND = QSizePolicy.Ignored, QSizePolicy.Expanding

        if n == 0:
            self.btn_scoreboard.setProperty("tab_selected", True)
            self.btn_overlays.setProperty("tab_selected", False)
            self.widget_scoreboard.setSizePolicy(EXPAND, EXPAND)
            self.widget_overlays.setSizePolicy(IGNORE, IGNORE)
        elif n == 1:
            self.btn_scoreboard.setProperty("tab_selected", False)
            self.btn_overlays.setProperty("tab_selected", True)
            self.widget_scoreboard.setSizePolicy(IGNORE, IGNORE)
            self.widget_overlays.setSizePolicy(EXPAND, EXPAND)

        self.widget_stack.setCurrentIndex(n)
        # update stylesheets
        self.btn_scoreboard.setStyle(self.btn_scoreboard.style())
        self.btn_overlays.setStyle(self.btn_scoreboard.style())
Пример #18
0
class MainView(QMainWindow):
    def __init__(self):
        super(MainView, self).__init__()
        self.setWindowTitle('Jira Helper')

        self.window = QStackedWidget()  # Create the main widget for the page

        main_window_widget = QWidget()
        main_window_layout = QGridLayout()
        main_window_widget.setLayout(main_window_layout)
        menu_widget = QWidget()
        menu_layout = QHBoxLayout()
        menu_widget.setLayout(menu_layout)
        main_window_layout.addWidget(menu_widget, 0, 0)
        main_window_layout.addWidget(self.window, 1, 0)
        self.setCentralWidget(main_window_widget)

        # Create a settings button
        self.settings_submit_button = QPushButton()
        self.settings_submit_button.setText("Settings")
        menu_layout.addWidget(self.settings_submit_button)

        # Create date time
        datetime_font = QFont("Times", 30)
        self.date = QLabel()
        self.date.setFont(datetime_font)
        self.time = QLabel()
        self.time.setFont(datetime_font)
        menu_layout.addWidget(self.date)
        menu_layout.addWidget(self.time)

        # Create a clean queue button
        self.clean_queue_button = QPushButton()
        self.clean_queue_button.setText("Clean Queue")
        self.clean_queue_button.setCheckable(True)
        menu_layout.addWidget(self.clean_queue_button)

    def update_datetime(self):
        '''Connected to a Qtimer to periodically update the date and time'''
        Qdate = QDate.currentDate()
        Qtime = QTime.currentTime()
        self.date.setText(Qdate.toString(Qt.DefaultLocaleLongDate))
        self.time.setText(Qtime.toString(Qt.DefaultLocaleLongDate))

    def transition_page(self):
        '''Connected to a Qtimer to periodically transition through the widgets stacked on self.window'''
        index_Id = self.window.currentIndex()
        if index_Id < self.window.count() - 1:
            self.window.setCurrentIndex(index_Id + 1)
        else:
            self.window.setCurrentIndex(0)
Пример #19
0
class receipt_view(QWidget, person_change_listener):

    __receipt_printouts = None
    __receipt_stack = None
    __person_list = None
    __model = None

    def __init__(self, model):
        super().__init__()
        self.__model = model
        self.__model.add_person_change_listeners(self)
        self.__receipt_printouts = list()
        # self.setWindowTitle("Receipt Tracker")

        self.__person_list = QComboBox()
        self.__person_list.adjustSize()
        self.__person_list.currentIndexChanged.connect(self.display)

        self.__receipt_stack = QStackedWidget()
        # for name in self.__model.get_names():
        #     printout = receipt_printout(name, self.__model)
        #     self.__receipt_printouts.add(printout)
        #     self.__receipt_stack.addWidget(printout)
        #     self.__person_list.addItem(name)

        receipt_layout = QVBoxLayout()
        receipt_layout.addWidget(self.__person_list)
        receipt_layout.addWidget(self.__receipt_stack)

        self.setLayout(receipt_layout)
        self.show()

    def display(self, i):
        self.__receipt_stack.setCurrentIndex(i)

    def person_update(self, model):
        for printout in self.__receipt_printouts:
            self.__receipt_stack.removeWidget(printout)

        for name in model.get_names():
            in_set = False
            for printout in self.__receipt_printouts:
                if name == printout.name:
                    in_set = True
            if not in_set:
                self.__receipt_printouts.append(receipt_printout(name, model))
                self.__person_list.addItem(name)

        for printout in self.__receipt_printouts:
            self.__receipt_stack.addWidget(printout)
Пример #20
0
class MapHolder(QWidget):
    def __init__(self, parent=None):
        super(MapHolder, self).__init__(parent=parent)
        self.map = IntervalMapClass(self)
        self.stack = QStackedWidget(self)
        self.stack.addWidget(self.map)
        self.stack.addWidget(QWidget(self))
        layout = QVBoxLayout(self)
        layout.addWidget(self.stack)

    def show_map(self):
        self.stack.setCurrentIndex(0)

    def hide_map(self):
        self.stack.setCurrentIndex(1)
Пример #21
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('CountDown')
        self.Stack = QStackedWidget()
        self.setCentralWidget(self.Stack)
        self.setWindowIcon(QIcon('CD_logo.png'))
        self.main_menu = MainMenu()
        self.Stack.addWidget(self.main_menu)
        self.problem_page = ProblemPage(0,30)
        self.Stack.addWidget(self.problem_page)
        self.Stack.setCurrentIndex(0)
        self.main_menu.next_page.clicked.connect(lambda: self.Stack.setCurrentIndex(1))
        self.problem_page.back_button.clicked.connect(lambda: self.Stack.setCurrentIndex(0))
        self.main_menu.next_page.clicked.connect(lambda: print(self.main_menu.selected_modes))
Пример #22
0
class SuttonKiosk(QScrollArea):
    def __init__(self, parent=None):
        super(SuttonKiosk, self).__init__(parent)
        self.widgetStack = QStackedWidget(self)
        #self.widgetStack.setGeometry(0,0, 320, 480)
        self.setGeometry(0, 0, 320, 480)
        classesWidgetWindow = ClassesWidgetWindow(self)

        #self.mainLayout.addWidget(self.widgetStack)
        #xself.setLayout(self.mainLayout)
        self.setWindowTitle("SuttonKiosk")
        self.setWidget(self.widgetStack)

    def setStackIndex(self, index):
        self.widgetStack.setCurrentIndex(index)
Пример #23
0
class Example(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()
        self.stacked_widget.currentChanged.connect(self.set_button_state)
        self.next_button.clicked.connect(self.next_page)
        self.prev_button.clicked.connect(self.prev_page)


    def initUI(self):

        self.next_button = QPushButton('Next')
        self.prev_button = QPushButton('Previous')
        self.next_button.setEnabled(False)
        self.prev_button.setEnabled(False)
        self.stacked_widget = QStackedWidget()

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.prev_button)
        hbox.addWidget(self.next_button)

        vbox = QVBoxLayout()
        vbox.addWidget(self.stacked_widget)
        vbox.addLayout(hbox)

        self.setLayout(vbox)


    def set_button_state(self, index):
        self.prev_button.setEnabled(index > 0)
        n_pages = len(self.stacked_widget)
        self.next_button.setEnabled( index % n_pages < n_pages - 1)

    def insert_page(self, widget, index=-1):
        self.stacked_widget.insertWidget(index, widget)
        self.set_button_state(self.stacked_widget.currentIndex())

    def next_page(self):
        new_index = self.stacked_widget.currentIndex()+1
        if new_index < len(self.stacked_widget):
            self.stacked_widget.setCurrentIndex(new_index)

    def prev_page(self):
        new_index = self.stacked_widget.currentIndex()-1
        if new_index >= 0:
            self.stacked_widget.setCurrentIndex(new_index)
Пример #24
0
class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.title = "Context Menu"
        self.left = 300
        self.top = 100
        self.width = 500
        self.height = 500
        self.IconName = "Icon/python.png"
        self.color = 'red'

        self.InitWindow()

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon(self.IconName))
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        #self.setStyleSheet('background-color:green')
    
        self.StackedWidget()
        self.show()
    
    def StackedWidget(self):
        vbox = QVBoxLayout()

        self.stackedwidget = QStackedWidget()
        vbox.addWidget(self.stackedwidget)

        for x in range(0, 8):
            label = QLabel("Stacked Child " + str(x))
            label.setFont(QtGui.QFont("Sanserif", 15))
            label.setStyleSheet('color:red')

            self.stackedwidget.addWidget(label)

            self.button = QPushButton("Stack " + str(x))
            self.button.setStyleSheet('background-color:green')
            self.button.page = x
            self.button.clicked.connect(self.btn_clicked)

            vbox.addWidget(self.button)

        self.setLayout(vbox)

    def btn_clicked(self):
        self.button = self.sender()
        self.stackedwidget.setCurrentIndex(self.button.page)
Пример #25
0
class StackWidget(QDialog):
    def __init__(self):
        super().__init__()

        self.title = "This is first thing"
        self.height = 700
        self.width = 1100
        self.top = 100
        self.left = 200
        self.iconName = "plioky.ico"

        self.setWindowIcon(QtGui.QIcon(self.iconName))
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.stacked()

        self.show()

    def stacked(self):

        vbox = QVBoxLayout()

        self.stacked_widget = QStackedWidget()

        vbox.addWidget(self.stacked_widget)

        for x in range(0, 8):
            label = QLabel("Stacked child" + str(x))
            label.setFont(QtGui.QFont("Sanserif", 15))
            label.setStyleSheet("color:red")

            self.stacked_widget.addWidget(label)

            self.button = QPushButton("Stack " + str(x))
            self.button.setStyleSheet("background-color:orange")

            self.button.page = x

            self.button.clicked.connect(self.btn_clicked)

            vbox.addWidget(self.button)

        self.setLayout(vbox)

    def btn_clicked(self):
        self.button = self.sender()
        self.stacked_widget.setCurrentIndex(self.button.page)
Пример #26
0
class QStackedWidgetDemo(QWidget):
    def __init__(self):
        super(QStackedWidgetDemo, self).__init__()
        self.setWindowTitle("堆栈窗口控件")
        self.resize(500, 300)
        self.list_widget = QListWidget()
        self.stack1 = QWidget()
        self.stack2 = QWidget()
        # self.stack3 = QWidget()
        self.stack = QStackedWidget()
        self.list_widget.currentRowChanged.connect(self.display)
        self.set_ui()
        self.stack1_ui()
        self.stack2_ui()

    def set_ui(self):
        self.list_widget.insertItem(0, "个人信息")
        self.list_widget.insertItem(1, "账户信息")
        self.stack.addWidget(self.stack1)
        self.stack.addWidget(self.stack2)
        _layout = QHBoxLayout()
        _layout.addWidget(self.list_widget)
        _layout.addWidget(self.stack)
        self.setLayout(_layout)

    def stack1_ui(self):
        _layout = QFormLayout()
        _layout.addRow("昵称: ", QLineEdit("zy01"))
        _layout.addRow("等级: ", QLineEdit("80"))
        self.stack1.setLayout(_layout)

    def stack2_ui(self):
        _layout = QHBoxLayout()
        _table = QTableWidget()
        _table.setRowCount(5)
        _table.setColumnCount(3)
        _table.setHorizontalHeaderLabels(["昵称", "登录名", "等级"])
        item1 = QTableWidgetItem("zy01")
        item2 = QTableWidgetItem("zy01")
        item3 = QTableWidgetItem("80")
        _table.setItem(0, 0, item1)
        _table.setItem(0, 1, item2)
        _table.setItem(0, 2, item3)
        _layout.addWidget(_table)
        self.stack2.setLayout(_layout)

    def display(self, _index):
        self.stack.setCurrentIndex(_index)
Пример #27
0
class Project_Clock(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        # Делаем макет для виджетов
        layer = QVBoxLayout(self)
        # Стакуем виджеты
        self.stack = QStackedWidget()
        self.stack.addWidget(TimesWidget())
        self.stack.addWidget(AlarmWidget())
        self.stack.addWidget(StopwatchWidget())
        self.stack.addWidget(TimerWidget())
        # Кнопка для показа виджета времени
        self.btn_times = QPushButton('Время', self)
        self.btn_times.move(0, 0)
        self.btn_times.resize(100, 25)
        self.btn_times.clicked.connect(self.times_on)
        # Кнопка для показа виджета будильника
        self.btn_alarm = QPushButton('Будильник', self)
        self.btn_alarm.move(100, 0)
        self.btn_alarm.resize(100, 25)
        self.btn_alarm.clicked.connect(self.alarm_on)
        # Кнопка для показа виджета секундомера
        self.btn_stopwatch = QPushButton('Секундомер', self)
        self.btn_stopwatch.move(200, 0)
        self.btn_stopwatch.resize(100, 25)
        self.btn_stopwatch.clicked.connect(self.stopwatch_on)
        # Кнопка для показа виджета таймера
        self.btn_timer = QPushButton('Таймер', self)
        self.btn_timer.move(300, 0)
        self.btn_timer.resize(100, 25)
        self.btn_timer.clicked.connect(self.timer_on)
        # Макет для кнопок
        btnLayout = QHBoxLayout()
        # Добавление кнопок в мает
        btnLayout.addWidget(self.btn_times)
        btnLayout.addWidget(self.btn_alarm)
        btnLayout.addWidget(self.btn_stopwatch)
        btnLayout.addWidget(self.btn_timer)
        # Добавление макета кнопок и стака с виджетами в основной макет
        layer.addWidget(self.stack)
        layer.addLayout(btnLayout)

    def initUI(self):
        self.setGeometry(100, 100, 500, 500)
        self.setWindowTitle('Часы')

    def times_on(self):
        self.stack.setCurrentIndex(0)

    def alarm_on(self):
        self.stack.setCurrentIndex(1)

    def stopwatch_on(self):
        self.stack.setCurrentIndex(2)

    def timer_on(self):
        self.stack.setCurrentIndex(3)
Пример #28
0
class ModelViewManager(QWidget):
    """
    Qt widget to select the viewer object
    """

    def __init__(self, lookup, spec):

        super().__init__()
        self._concrete_model = None
        self.results = None
        self.lookup = lookup

        # output viewers
        self.viewer = {'Tabular Viewer': 'TabularModelViewer'}
        if hasattr(spec, 'viewers'):
            self.viewer.update(spec.viewers)
        self.stacked_widget = QStackedWidget()
        for cl in self.viewer.values():
            o = create_viewer(cl, lookup)
            self.stacked_widget.addWidget(o)

        # viewer combobox
        self.viewer_combobox = QComboBox()
        self.viewer_combobox.addItems(self.viewer.keys())
        self.viewer_combobox.currentIndexChanged.connect(self.viewer_changed)

        # arrange widgets in grid
        self.grid_layout = QGridLayout()
        self.grid_layout.addWidget(self.viewer_combobox, 0, 0)
        self.grid_layout.addWidget(self.stacked_widget, 1, 0)
        self.setLayout(self.grid_layout)

    @property
    def concrete_model(self):
        return self._concrete_model

    @concrete_model.setter
    def concrete_model(self, model):
        logging.info('Concrete model changed in ModelViewManager')
        self._concrete_model = model
        # propagate model to viewers
        for view in self.stacked_widget.children():
            view.concrete_model = model

    def viewer_changed(self, i):
        new_viewer_name = self.viewer_combobox.currentText()
        logging.info('Viewer changed to %s' % new_viewer_name)
        self.stacked_widget.setCurrentIndex(i)
Пример #29
0
 def __init__(self, pluginsHelp: dict, parent=None, icon=None):
     QWidget.__init__(self, parent)
     CustomTitleBarWindowMixin.__init__(self, init=True, title=_("Help"))
     self.resize(800, 700)
     layout = QHBoxLayout()
     layout.setContentsMargins(0, 0, 0, 0)
     self.contentWidget.setLayout(layout)
     # self.setLayout(layout)
     itemList = QListWidget()
     itemList.setProperty("class", "helpList")
     tabs = QStackedWidget()
     layout.addWidget(itemList)
     layout.addWidget(tabs)
     layout.setStretch(0, 1)
     layout.setStretch(1, 4)
     for name, help in pluginsHelp.items():
         tab = QWidget()
         tab.setProperty("class", "helpTab")
         tabLayout = QVBoxLayout()
         tab.setLayout(tabLayout)
         if type(help) == str:
             tabLabel = ScrollLabel(help)
         else:
             tabLabel = help
         tabLayout.addWidget(tabLabel)
         tabs.addWidget(tab)
         itemList.addItem(name)
     itemList.setCurrentRow(0)
     itemList.currentRowChanged.connect(
         lambda idx: tabs.setCurrentIndex(idx))
     self.show()
class StackWidget(QDialog):
    def __init__(self):
        super().__init__()

        self.title = "PyQt5 Stacked Widget"
        self.top = 100
        self.left = 100
        self.width = 400
        self.height = 300

        self.stacked_widget()
        self.InitWindow()

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("home.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.show()

    def stacked_widget(self):

        vbox = QVBoxLayout()

        self.stackedWidget = QStackedWidget()
        vbox.addWidget(self.stackedWidget)

        for x in range(0, 8):
            label = QLabel("Stacked Child" + str(x))
            label.setFont(QtGui.QFont("Sanserif", 15))
            label.setStyleSheet("color:red")

            self.stackedWidget.addWidget(label)

            self.button = QPushButton("Stack " + str(x))
            self.button.setStyleSheet('background-color:green')

            self.button.page = x
            self.button.clicked.connect(self.btn_clicked)

            vbox.addWidget(self.button)

        self.setLayout(vbox)

    def btn_clicked(self):
        self.button = self.sender()
        self.stackedWidget.setCurrentIndex(self.button.page - 1)
Пример #31
0
class MainWidget(QFrame):
    def __init__(self):
        super().__init__()
        self.back_button = PushButton()
        self.back_button.setFixedWidth(55)
        self.back_button.setFixedHeight(30)
        self.back_button.setIcon(QIcon(resource_path("back_arrow.png")))
        # so we can reference just this button in css
        self.back_button.setObjectName("backButton")
        self.back_button.clicked.connect(lambda: self.set_index(0))
        # offset by a bit so we're not right against the window border
        margins = self.back_button.contentsMargins()
        margins.setLeft(10)
        margins.setTop(10)
        self.back_button.setContentsMargins(margins)

        self.stacked_widget = QStackedWidget()

        window_selector = WindowSelector()
        window_selector.visualize_button_clicked.connect(
            lambda: self.set_index(1))
        window_selector.bulk_investigation_button_clicked.connect(
            lambda: self.set_index(2))

        self.analysis_selection = AnalysisSelection()
        self.cg_classic = CircleguardClassic()

        self.stacked_widget.addWidget(window_selector)
        self.stacked_widget.addWidget(self.analysis_selection)
        self.stacked_widget.addWidget(self.cg_classic)

        index_map = {"selection": 0, "visualization": 1, "investigation": 2}
        index = index_map[get_setting("default_page")]
        self.set_index(index)

        layout = QVBoxLayout()
        layout.addWidget(self.back_button)
        layout.addWidget(self.stacked_widget)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        self.setLayout(layout)

    def set_index(self, index):
        # don't show the back button on the selection page itself
        self.back_button.hide() if index == 0 else self.back_button.show()
        self.stacked_widget.setCurrentIndex(index)
Пример #32
0
class Root(QMainWindow):
    task_list_index = 0
    task_view_index = 1

    def __init__(self):
        super().__init__()
        self.model = None
        self.task_view = None
        self.initUI()

    def initUI(self):
        # self.cal = QCalendarWidget(self)
        # self.cal.setVerticalHeaderFormat(QCalendarWidget.NoVerticalHeader)
        # self.cal.setGeometry(0, 0, 250, 250)

        self.model = TaskModel()
        self.central = QStackedWidget()

        task_list = TaskList(self.model)
        task_list.open.connect(self.task_open)
        self.central.insertWidget(Root.task_list_index, task_list)

        self.task_view = TaskView(self.model)
        self.task_view.close.connect(self.task_view_close)
        self.central.insertWidget(Root.task_view_index, self.task_view)

        self.central.setCurrentIndex(Root.task_list_index)
        self.setCentralWidget(self.central)

        # QDialog flags:
        #   Qt.Dialog |
        #   Qt.WindowTitleHint |
        #   Qt.WindowSystemMenuHint |
        #   Qt.WindowContextHelpButtonHint |
        #   Qt.WindowCloseButtonHint
        self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
        self.setGeometry(700, 300, 250, 300)
        self.setWindowTitle('Calendar')

    @pyqtSlot(int)
    def task_open(self, index):
        self.task_view.set_task(index)
        self.central.setCurrentIndex(Root.task_view_index)

    @pyqtSlot()
    def task_view_close(self):
        self.central.setCurrentIndex(Root.task_list_index)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
class MainView(base, form):
    def __init__(self, pipeline, parent=None):

        super(base, self).__init__(parent)
        self.setupUi(self)
        self.pipeline = pipeline
        self.pip_widgets = []
        self.default_pips = []

        self.draw_ui()
        self.connect_ui()

    def register_observers(self):
        pass

    def connect_ui(self):
        """
        This function connects the ui using signals from the
        ui elements and its method counterparts.
        """
        self.input_btn.clicked.connect(self.set_input_url)
        self.output_btn.clicked.connect(self.set_output_url)
        self.save_btn.clicked.connect(self.save_pipeline)
        self.load_favorite_pipelines()
        self.fav_pips_combo_box.activated.connect(self.select_default_pip)
        self.run_btn.clicked.connect(self.run)
        self.delete_btn.clicked.connect(self.trash_pipeline)
        self.add_btn.clicked.connect(lambda: self.add_pipe_entry_new())

    def draw_ui(self):
        """
        This function draws all additional UI elements. If you want the
        application to display any additional things like a button you can
        either add it in the QtDesigner or declare it here.
        """

        # *TODO* Create these ones with Qt Designer and put them into select_cat_alg_vbox_layout. I failed
        self.ComboxCategories = QComboBox()
        self.stackedWidgetComboxesAlgorithms = QStackedWidget()
        self.select_cat_alg_vbox_layout.addWidget(self.ComboxCategories)
        self.select_cat_alg_vbox_layout.addWidget(self.stackedWidgetComboxesAlgorithms)
        self.ComboxCategories.hide()


        """
        This function is concerned with drawing all non static elements  into the
        GUI.
        """
        """self.set_pip_title("A. Junius2")

        self.set_preset(["A.Junius", "test", "test", "test"])


        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_pip_entry("../assets/images/P.png", "Preprocessing - adaptive trehsold watershed")
        self.add_cat_image("../assets/images/seg_fav.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")
        self.add_cat_image("../assets/images/wing.jpeg", "Preprocessing")

        self.main_image_label.setPixmap(QtGui.QPixmap("wing.jpeg"))

        category_combo_box = ComboBoxWidget("type")
        category_combo_box.add_item("Preprocessing", "../assets/images/P.png")
        category_combo_box.add_item("Segmentation", "../assets/images/S.png")
        category_combo_box.add_item("Graph Detection", "../assets/images/D.png")
        category_combo_box.add_item("Graph Filtering", "../assets/images/F.png")

        alg_combo_box = ComboBoxWidget("algorithm")
        alg_combo_box.add_item("Otsus")
        alg_combo_box.add_item("Guo Hall")
        alg_combo_box.add_item("Adaptive Treshold")

        slider_1 = SliderWidget("slider1das", 0, 10, 1, 4, True)
        slider_2 = SliderWidget("slider1", 0, 10, 2, 4, False)
        slider_3 = SliderWidget("sliderböadsad", 0, 10, 1, 4, True)
        slider_4 = SliderWidget("sliderböadsad", 0, 10, 1, 4, True)
        slider_5 = SliderWidget("sliderböadsad", 0, 10, 1, 4, True)
        checkbox_1 = CheckBoxWidget("checkbox1", True)

        self.setting_widget_vbox_layout.addWidget(category_combo_box)
        self.setting_widget_vbox_layout.addWidget(alg_combo_box)
        self.setting_widget_vbox_layout.addWidget(slider_1)
        self.setting_widget_vbox_layout.addWidget(slider_2)
        self.setting_widget_vbox_layout.addWidget(slider_3)
        self.setting_widget_vbox_layout.addWidget(slider_4)
        self.setting_widget_vbox_layout.addWidget(slider_5)
        self.setting_widget_vbox_layout.addWidget(checkbox_1)
        self.setting_widget_vbox_layout.setAlignment(Qt.AlignTop)"""

    def set_pip_title(self, title):
        """
        Sets the title of the current selected pipeline in the ui.

        Args:
            | *title*: the title of the pipeline
            | *label_ref*: the reference to the label.
        """
        self.current_pip_label.setText(title)

    def load_dark_theme(self, application):
        """
        This function is called to load the white theme with
        all its icons for the buttons and the css file.
        Args:
            application: the cureent app instance
        """
        # load buttons
        pixmap_icon = QtGui.QPixmap("./assets/images/add_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        self.add_btn.setIcon(q_icon)

        pixmap_icon = QtGui.QPixmap("./assets/images/trash_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        self.delete_btn.setIcon(q_icon)

        pixmap_icon = QtGui.QPixmap("./assets/images/diskette_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        self.save_btn.setIcon(q_icon)

        pixmap_icon = QtGui.QPixmap("./assets/images/up-arrow_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        self.input_btn.setIcon(q_icon)

        pixmap_icon = QtGui.QPixmap("./assets/images/folder_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        self.output_btn.setIcon(q_icon)

    @pyqtSlot(int)
    def select_default_pip(self, index):
        """
        This is the slot for the Pipeline combobox in the ui
        Args:
            index: index of the option currently selected
        """

        # delete current pipeline

        self.trash_pipeline()

        # get url and name
        name, url = self.default_pips[index - 1]

        # parse the json in the model
        self.pipeline.load_pipeline_json(url)

        print("PARSER" + str(self.pipeline.executed_cats[0].active_algorithm))
        print("PARSER" + str(self.pipeline.executed_cats[1].active_algorithm))

        # set the title
        self.set_pip_title(name)

        # Create an entry in the pipeline widget for every step in the pipeline
        for i in range(0, len(self.pipeline.executed_cats)):
            self.add_pipe_entry_new(i)
            self.scroll_down_pip()

            """for widget in alg_widgets:
                self.setting_widget_vbox_layout.addWidget(widget)"""

    def trash_pipeline(self):
        """
        This method clears the complete pipeline while users clicked the trash
        button.
        """
        # remove all entries in the pipeline list

        while self.pip_widget_vbox_layout.count():
            child = self.pip_widget_vbox_layout.takeAt(0)
            child.widget().deleteLater()

        while self.stackedWidget_Settings.currentWidget() is not None:
            self.stackedWidget_Settings.removeWidget(self.stackedWidget_Settings.currentWidget())
            self.settings_collapsable.setTitle("")

        # remove the pipeline name
        self.set_pip_title("")

        # remove all entries int the executed_cats of the model pipeline
        del self.pipeline.executed_cats[:]

        # remove all widgets
        del self.pip_widgets[:]

        # remove category algorith dropdown
        self.remove_cat_alg_dropdown()

        # remove all entries from the pipeline model

        del self.pipeline.executed_cats[:]

    @pyqtSlot()
    def run(self):
        """
        This method runs the the pipeline by calling the process methode
        in pipeline
        """

        self.pipeline.process()

    @pyqtSlot()
    def set_input_url(self):
        """
        This method sets the url for the input image in the pipeline.
        """
        url = QtWidgets.QFileDialog.getOpenFileNames()
        if url[0]:
            print(url[0])
            print(url[0][0])
            self.lineEdit.setText(url[0][0])
            self.pipeline.set_input(url[0][0])


    @pyqtSlot()
    def set_output_url(self):
        """
        This method sets the url for the output folder in the pipeline.
        Args:
            url: the url to the output folder a user selected in the ui
        """
        url = QtWidgets.QFileDialog.getExistingDirectory()
        if url:
            print(url)
            print(url)
            self.custom_line_edit.setText(url)
            self.pipeline.set_output_dir(url)

    def load_favorite_pipelines(self):
        """
        Scans the directory for default pipelines to display all available items
        """
        self.fav_pips_combo_box.addItem("Please Select")

        # scan the directory for default pipelines
        for file in os.listdir("./_default_pipelines"):
            if file.endswith(".json"):
                name = file.split(".")[0]
                url = os.path.abspath("./_default_pipelines" + "/" + file)
                self.default_pips.append([name, url])
                self.fav_pips_combo_box.addItem(name)

    @pyqtSlot()
    def save_pipeline(self):
        """
        Saves the pipeline as a json at the users file system.
        """
        url = str(QtWidgets.QFileDialog.getSaveFileName()[0])

        split_list = url.split("/")
        name = split_list[len(split_list) - 1].split(".")[0]
        del split_list[len(split_list) - 1]
        url = url.replace(name, "")
        self.pipeline.save_pipeline_json(name, url)

    @pyqtSlot(int)
    def remove_pip_entry(self, pipe_entry_widget, settings_widget, cat=None):
        """
        Removes the pip entry at the given position in the ui
        Args:
            pipeline_index (object):
            settings_widget:
            position: position at which the pip entry gets removed
        """

        # remove pipeline entry widget from ui
        self.pip_widget_vbox_layout.removeWidget(pipe_entry_widget)
        pipe_entry_widget.deleteLater()

        # remove it settings widgets from ui
        if settings_widget is not None:
            if self.stackedWidget_Settings.currentWidget() == settings_widget:
                self.stackedWidget_Settings.hide()
                self.remove_cat_alg_dropdown()
                self.settings_collapsable.setTitle("Settings")

            self.stackedWidget_Settings.removeWidget(settings_widget)

        # remove in model
        if cat is not None:
            print("Remove entry at pos " + str(self.pipeline.get_index(cat)) + " " + str(cat))
            self.pipeline.delete_category(self.pipeline.get_index(cat))

    def change_pip_entry_alg(self, position, new_category, new_algorithm, pipe_entry_widget, settings_widget):
        """
        Changes the selected algorithm of the pipeline entry at the position.
        Afterwards create all widgets for this algorithm instance
        Args:
            position: the position of the pipeline entry
            algorithm: the selected algorithm for this category
        """
        print("Position to be changed:" + str(position))
        print("Pipeline length: " + str(len(self.pipeline.executed_cats)))

        old_cat = self.pipeline.executed_cats[position]
        old_alg = old_cat.active_algorithm
        print("Old Cat found in pipeline: " + str(old_cat))
        print("Old Alg: found in pipeline:" + str(old_alg))

        print("New Category given:" + str(new_category))
        print("New Algorithm given:" + str(new_algorithm))

        # set in model
        self.pipeline.change_category(new_category, position)
        self.pipeline.change_algorithm(new_algorithm, position)

        new_cat = self.pipeline.executed_cats[position]
        new_alg = new_cat.active_algorithm

        # change settings widgets
        self.remove_pip_entry(pipe_entry_widget, settings_widget)
        (new_pipe_entry_widget, new_settings_widget) = self.add_pipe_entry_new(position)

        self.stackedWidget_Settings.show()
        self.stackedWidget_Settings.setCurrentIndex(position)
        self.settings_collapsable.setTitle(new_alg.get_name() + " Settings")

        self.remove_cat_alg_dropdown()
        self.create_cat_alg_dropdown(position, new_pipe_entry_widget, new_settings_widget)
        self.set_cat_alg_dropdown(new_cat, new_alg)


        print("New Cat found in pipeline: " + str(new_cat))
        print("New Alg found in pipeline: " + str(new_alg))


    def load_settings_widgets_from_pipeline_groupbox(self, position):
        """
        Extracts all widgets from a single algorithm and returns a QBoxLayout
        Args:
            alg: the alg instance we extract from

        Returns: a QBoxLayout containing all widgets for this particular alg.

        """

        alg = self.pipeline.executed_cats[position].active_algorithm

        print("alg " + str(alg))
        print("cat " + str(self.pipeline.executed_cats[position]))

        empty_flag = True

        groupOfSliders = QGroupBox()
        sp = QSizePolicy()
        sp.setVerticalPolicy(QSizePolicy.Preferred)
        # groupOfSliders.setSizePolicy(sp)
        groupOfSliderssLayout = QBoxLayout(QBoxLayout.TopToBottom)
        groupOfSliderssLayout.setContentsMargins(0, -0, -0, 0)
        groupOfSliderssLayout.setAlignment(Qt.AlignTop)
        groupOfSliderssLayout.setSpacing(0)

        print("Build Slider @ "+ str(position))

        # create integer sliders
        for slider in alg.integer_sliders:
            empty_flag = False
            print("slider.value " + str(slider.value))
            print("slider " + str(slider))
            #print(alg.get_name() + ": add slider (int).")
            groupOfSliderssLayout.addWidget(
                SliderWidget(slider.name, slider.lower, slider.upper, slider.step_size, slider.value,
                             slider.set_value, False))

        # create float sliders
        for slider in alg.float_sliders:
            empty_flag = False
            #print(alg.get_name() + ": add slider (float).")
            groupOfSliderssLayout.addWidget(
                SliderWidget(slider.name, slider.lower, slider.upper, slider.step_size, slider.value,
                             slider.set_value, True), 0, Qt.AlignTop)

        # create checkboxes
        for checkbox in alg.checkboxes:
            empty_flag = False
            #print(alg.get_name() + ": add checkbox.")
            groupOfSliderssLayout.addWidget(CheckBoxWidget(checkbox.name, checkbox.value, checkbox.set_value), 0,
                                            Qt.AlignTop)

        # create dropdowns
        for combobox in alg.drop_downs:
            empty_flag = False
            #print(alg.get_name() + ": add combobox.")
            groupOfSliderssLayout.addWidget(
                ComboBoxWidget(combobox.name, combobox.options, combobox.set_value, combobox.value), 0, Qt.AlignTop)

        if empty_flag:
            label = QLabel()
            label.setText("This algorithm has no Settings.")
            groupOfSliderssLayout.addWidget(label, 0, Qt.AlignHCenter)

        groupOfSliders.setLayout(groupOfSliderssLayout)

        return groupOfSliders

    def create_cat_alg_dropdown(self, cat_position, pipe_entry_widget, settings_widget):

        """
        Args:
            last_cat (object):
        """
        layout = self.select_cat_alg_vbox_layout
        cat = self.pipeline.executed_cats[cat_position]

        last_cat = None

        # Show only allowed categories in dropdown
        if len(self.pipeline.executed_cats) > 1:
            last_cat = self.pipeline.executed_cats[cat_position - 1]

        # Combobox for selecting Category
        self.ComboxCategories.show()
        self.ComboxCategories.setFixedHeight(30)
        self.ComboxCategories.addItem("<Please Select Category>")

        self.stackedWidgetComboxesAlgorithms = QStackedWidget()
        self.stackedWidgetComboxesAlgorithms.setFixedHeight(30)
        self.stackedWidgetComboxesAlgorithms.hide()

        def setCurrentIndexCat(index):
            #print("Set Cat")
            if self.ComboxCategories.currentIndex() == 0:
                self.stackedWidgetComboxesAlgorithms.hide()
            else:
                self.stackedWidgetComboxesAlgorithms.show()
                self.stackedWidgetComboxesAlgorithms.setCurrentIndex(index - 1)

        for category_name in self.pipeline.report_available_cats(last_cat):

            # Add Category to combobox
            self.ComboxCategories.addItem(category_name)
            tmp1 = QComboBox()
            tmp1.addItem("<Please Select Algorithm>")
            tmp1.setFixedHeight(30)
            category = self.pipeline.get_category(category_name)
            #self.current_index = -1

            def setCurrentIndexAlg(index):
                if self.ComboxCategories.currentIndex() == 0 or self.stackedWidgetComboxesAlgorithms.currentWidget().currentIndex() == 0:
                    pass
                else: #self.current_index != index:
                    self.change_pip_entry_alg(self.pipeline.get_index(cat), self.ComboxCategories.currentText(),
                                              self.stackedWidgetComboxesAlgorithms.currentWidget().currentText(),
                                              pipe_entry_widget, settings_widget)
                    #self.current_index = index

            tmp1.activated.connect(setCurrentIndexAlg)

            for algorithm_name in self.pipeline.get_all_algorithm_list(category):
                tmp1.addItem(algorithm_name)

            self.stackedWidgetComboxesAlgorithms.addWidget(tmp1)

        layout.addWidget(self.ComboxCategories)
        layout.addWidget(self.stackedWidgetComboxesAlgorithms)

        self.ComboxCategories.activated.connect(setCurrentIndexCat)

    def set_cat_alg_dropdown(self, category, algorithm):

        indexC = self.ComboxCategories.findText(category.get_name())
        #print("IndexC " + str(indexC))
        self.ComboxCategories.setCurrentIndex(indexC)
        self.stackedWidgetComboxesAlgorithms.show()
        self.stackedWidgetComboxesAlgorithms.setCurrentIndex(indexC - 1)
        indexA = self.stackedWidgetComboxesAlgorithms.currentWidget().findText(algorithm.get_name())
        #print("IndexA " + str(indexA))
        self.stackedWidgetComboxesAlgorithms.currentWidget().setCurrentIndex(indexA)

    def remove_cat_alg_dropdown(self):

        """

        Returns:
            object:
        """
        self.ComboxCategories.clear()

        while self.stackedWidgetComboxesAlgorithms.currentWidget() is not None:
            self.stackedWidgetComboxesAlgorithms.removeWidget(self.stackedWidgetComboxesAlgorithms.currentWidget())

        while self.select_cat_alg_vbox_layout.count():
            child = self.select_cat_alg_vbox_layout.takeAt(0)
            child.widget().hide()

    def scroll_down_pip(self):
        self.pip_scroll.verticalScrollBar().setSliderPosition(self.pip_scroll.verticalScrollBar().maximum())

    def add_pipe_entry_new(self, position=None):
        """
            Creates a entry in the ui pipeline with a given position in pipeline.
            It also creates the corresponding settings widget.
            """
        # create an widget that displays the pip entry in the ui and connect the remove button

        pip_main_widget = QWidget()
        pip_main_widget.setFixedHeight(70)
        pip_main_widget.setFixedWidth(300)
        pip_main_layout = QHBoxLayout()
        pip_main_widget.setLayout(pip_main_layout)

        new_marker = False

        if position is None:
            position = len(self.pipeline.executed_cats)
            cat = self.pipeline.new_category(position)
            label = "<Click to specify new step>"
            icon = None
            new_marker = True
        else:
            cat = self.pipeline.executed_cats[position]
            alg = cat.active_algorithm
            label = alg.get_name()
            icon = cat.get_icon()
            new_marker = False

        pixmap = QPixmap(icon)
        pixmap_scaled_keeping_aspec = pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio)
        pixmap_label = QtWidgets.QLabel()
        pixmap_label.setPixmap(pixmap_scaled_keeping_aspec)

        pip_up_down = QWidget()
        pip_up_down.setFixedHeight(70)
        pip_up_down_layout = QVBoxLayout()
        pip_up_down.setLayout(pip_up_down_layout)

        up_btn = QToolButton()
        dw_btn = QToolButton()

        up_btn.setArrowType(Qt.UpArrow)
        up_btn.setFixedHeight(25)
        dw_btn.setArrowType(Qt.DownArrow)
        dw_btn.setFixedHeight(25)

        pip_up_down_layout.addWidget(up_btn)
        pip_up_down_layout.addWidget(dw_btn)

        string_label = QLabel()
        string_label.setText(label)
        string_label.setFixedWidth(210)

        btn = QtWidgets.QPushButton()
        btn.setFixedSize(20, 20)

        pixmap_icon = QtGui.QPixmap("./assets/images/delete_x_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        btn.setIcon(q_icon)

        pip_main_layout.addWidget(pip_up_down, Qt.AlignVCenter)
        pip_main_layout.addWidget(pixmap_label, Qt.AlignVCenter)
        pip_main_layout.addWidget(string_label, Qt.AlignLeft)
        pip_main_layout.addWidget(btn, Qt.AlignVCenter)

        self.pip_widget_vbox_layout.insertWidget(position, pip_main_widget)

        # Create the corresponding settings widget and connect it
        self.settings_collapsable.setTitle("Settings")
        self.stackedWidget_Settings.hide()
        settings_main_widget = None
        if not new_marker:
            settings_main_widget = self.load_settings_widgets_from_pipeline_groupbox(position)
            self.stackedWidget_Settings.insertWidget(position, settings_main_widget)

        def show_settings():
            # Set background color while widget is selected. Doesn't work because of theme? *TODO*
            p = pip_main_widget.palette()
            p.setColor(pip_main_widget.backgroundRole(), Qt.red)
            pip_main_widget.setPalette(p)

            if not new_marker:
                self.stackedWidget_Settings.show()
                self.stackedWidget_Settings.setCurrentIndex(self.pipeline.get_index(cat))
                self.settings_collapsable.setTitle(alg.get_name() + " Settings")
            else:
                self.stackedWidget_Settings.hide()

            # Create drop down for cats and algs
            self.remove_cat_alg_dropdown()
            self.create_cat_alg_dropdown(self.pipeline.get_index(cat), pip_main_widget, settings_main_widget)

            if not new_marker:
                self.set_cat_alg_dropdown(cat, alg)

        # Connect Button to remove step from pipeline
        def delete_button_clicked():
            self.remove_cat_alg_dropdown()
            self.remove_pip_entry(pip_main_widget, settings_main_widget, cat)

        self.clickable(pixmap_label).connect(show_settings)
        self.clickable(string_label).connect(show_settings)
        btn.clicked.connect(delete_button_clicked)


        return (pip_main_widget, settings_main_widget)



    def add_pip_entry_empty(self):
        """
        Creates an blank entry in the ui pipeline since the user still needs to specify
        a type and an algorithm of the category.
        It also creates the corresponding settings widget.
        """
        # create an widget that displays the pip entry in the ui and connect the remove button
        pip_main_widget = QWidget()
        pip_main_widget.setFixedHeight(70)
        pip_main_widget.setFixedWidth(300)
        pip_main_layout = QHBoxLayout()
        pip_main_widget.setLayout(pip_main_layout)

        label = "<Click to specify new step>"
        icon = None

        pixmap = QPixmap(icon)
        pixmap_scaled_keeping_aspec = pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio)
        pixmap_label = QtWidgets.QLabel()
        pixmap_label.setPixmap(pixmap_scaled_keeping_aspec)

        pip_up_down = QWidget()
        pip_up_down.setFixedHeight(70)
        pip_up_down_layout = QVBoxLayout()
        pip_up_down.setLayout(pip_up_down_layout)

        up_btn = QToolButton()
        dw_btn = QToolButton()

        up_btn.setArrowType(Qt.UpArrow)
        up_btn.setFixedHeight(25)
        dw_btn.setArrowType(Qt.DownArrow)
        dw_btn.setFixedHeight(25)

        pip_up_down_layout.addWidget(up_btn)
        pip_up_down_layout.addWidget(dw_btn)

        string_label = QLabel()
        string_label.setText(label)
        string_label.setFixedWidth(210)

        btn = QtWidgets.QPushButton()
        btn.setFixedSize(20, 20)

        pixmap_icon = QtGui.QPixmap("./assets/images/delete_x_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        btn.setIcon(q_icon)

        pip_main_layout.addWidget(pip_up_down, Qt.AlignVCenter)
        pip_main_layout.addWidget(pixmap_label, Qt.AlignVCenter)
        pip_main_layout.addWidget(string_label, Qt.AlignLeft)
        pip_main_layout.addWidget(btn, Qt.AlignVCenter)

        cat_position = len(self.pipeline.executed_cats)

        self.pip_widget_vbox_layout.insertWidget(cat_position, pip_main_widget)
        index = self.pip_widget_vbox_layout.indexOf(pip_main_widget)
        #print(index)

        # Create the corresponding empty settings widget and connect it
        # settings = self.load_widgets_from_cat_groupbox(cat_position) *TODO* EMPTY

        self.settings_collapsable.setTitle("Settings")
        self.stackedWidget_Settings.hide()

        # Add new step to pipeline
        new_category = self.pipeline.new_category(cat_position)

        print("Create new entry " + str(new_category))
        print("Pipeline length: " + str(len(self.pipeline.executed_cats)) + ".")

        settings_main_widget = None

        # Connect pipeline entry with corresponding settings widget
        def show_settings():
            #print("click")
            self.stackedWidget_Settings.show()

            self.remove_cat_alg_dropdown()

            # Create drop down for cats and algs
            self.create_cat_alg_dropdown(self.pipeline.get_index(new_category), pip_main_widget, settings_main_widget)
            self.stackedWidget_Settings.hide()

        # Connect Button to remove step from pipeline
        def delete_button_clicked():
            self.remove_cat_alg_dropdown()
            self.remove_pip_entry(pip_main_widget, settings_main_widget, new_category)

        self.clickable(pixmap_label).connect(show_settings)
        self.clickable(string_label).connect(show_settings)
        btn.clicked.connect(delete_button_clicked)

        self.scroll_down_pip()

    def add_pip_entry(self, cat_position):
        """
        Creates a entry in the ui pipeline with a given position in pipeline.
        It also creates the corresponding settings widget.
        """
        # create an widget that displays the pip entry in the ui and connect the remove button

        pip_main_widget = QWidget()
        pip_main_widget.setFixedHeight(70)
        pip_main_widget.setFixedWidth(300)
        pip_main_layout = QHBoxLayout()
        pip_main_widget.setLayout(pip_main_layout)

        cat = self.pipeline.executed_cats[cat_position]
        alg = cat.active_algorithm
        label = alg.get_name()
        icon = cat.get_icon()

        pixmap = QPixmap(icon)
        pixmap_scaled_keeping_aspec = pixmap.scaled(30, 30, QtCore.Qt.KeepAspectRatio)
        pixmap_label = QtWidgets.QLabel()
        pixmap_label.setPixmap(pixmap_scaled_keeping_aspec)

        pip_up_down = QWidget()
        pip_up_down.setFixedHeight(70)
        pip_up_down_layout = QVBoxLayout()
        pip_up_down.setLayout(pip_up_down_layout)

        up_btn = QToolButton()
        dw_btn = QToolButton()

        up_btn.setArrowType(Qt.UpArrow)
        up_btn.setFixedHeight(25)
        dw_btn.setArrowType(Qt.DownArrow)
        dw_btn.setFixedHeight(25)

        pip_up_down_layout.addWidget(up_btn)
        pip_up_down_layout.addWidget(dw_btn)

        string_label = QLabel()
        string_label.setText(label)
        string_label.setFixedWidth(210)

        btn = QtWidgets.QPushButton()
        btn.setFixedSize(20, 20)

        pixmap_icon = QtGui.QPixmap("./assets/images/delete_x_white.png")
        q_icon = QtGui.QIcon(pixmap_icon)
        btn.setIcon(q_icon)

        pip_main_layout.addWidget(pip_up_down, Qt.AlignVCenter)
        pip_main_layout.addWidget(pixmap_label, Qt.AlignVCenter)
        pip_main_layout.addWidget(string_label, Qt.AlignLeft)
        pip_main_layout.addWidget(btn, Qt.AlignVCenter)

        self.pip_widget_vbox_layout.insertWidget(cat_position, pip_main_widget)
        index = self.pip_widget_vbox_layout.indexOf(pip_main_widget)
        #print(index)

        # Create the corresponding settings widget and connect it
        settings_main_widget = self.load_settings_widgets_from_pipeline_groupbox(cat_position)

        self.settings_collapsable.setTitle("Settings")
        self.stackedWidget_Settings.hide()
        self.stackedWidget_Settings.insertWidget(cat_position, settings_main_widget)

        #print("Read from pipeline entry " + str(cat))
        #print("Pipeline length: " + str(len(self.pipeline.executed_cats)) + ".")

        def show_settings():
            # Set background color while widget is selected. Doesn't work because of theme? *TODO*
            p = pip_main_widget.palette()
            p.setColor(pip_main_widget.backgroundRole(), Qt.red)
            pip_main_widget.setPalette(p)

            self.stackedWidget_Settings.show()
            self.stackedWidget_Settings.setCurrentIndex(self.pipeline.get_index(cat))
            self.settings_collapsable.setTitle(alg.get_name() + " Settings")

            self.remove_cat_alg_dropdown()

            # Create drop down for cats and algs
            self.create_cat_alg_dropdown(self.pipeline.get_index(cat), pip_main_widget, settings_main_widget)
            #print(cat)
            #print(alg)
            self.set_cat_alg_dropdown(cat, alg)

        # Connect Button to remove step from pipeline
        def delete_button_clicked():
            self.remove_pip_entry(pip_main_widget, settings_main_widget, cat)

        self.clickable(pixmap_label).connect(show_settings)
        self.clickable(string_label).connect(show_settings)
        btn.clicked.connect(delete_button_clicked)

        return (pip_main_widget, settings_main_widget)

    # https://wiki.python.org/moin/PyQt/Making%20non-clickable%20widgets%20clickable
    def clickable(self, widget):
        """
        Convert any widget to a clickable widget.
        """

        class Filter(QObject):

            clicked = pyqtSignal()

            def eventFilter(self, obj, event):

                if obj == widget:
                    if event.type() == QEvent.MouseButtonPress:
                        if obj.rect().contains(event.pos()):
                            self.clicked.emit()
                            # The developer can opt for .emit(obj) to get the object within the slot.
                            return True

                return False

        filter = Filter(widget)
        widget.installEventFilter(filter)
        return filter.clicked
Пример #34
0
class E5SideBar(QWidget):
    """
    Class implementing a sidebar with a widget area, that is hidden or shown,
    if the current tab is clicked again.
    """
    Version = 1
    
    North = 0
    East = 1
    South = 2
    West = 3
    
    def __init__(self, orientation=None, delay=200, parent=None):
        """
        Constructor
        
        @param orientation orientation of the sidebar widget (North, East,
            South, West)
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        @param parent parent widget (QWidget)
        """
        super(E5SideBar, self).__init__(parent)
        
        self.__tabBar = QTabBar()
        self.__tabBar.setDrawBase(True)
        self.__tabBar.setShape(QTabBar.RoundedNorth)
        self.__tabBar.setUsesScrollButtons(True)
        self.__tabBar.setDrawBase(False)
        self.__stackedWidget = QStackedWidget(self)
        self.__stackedWidget.setContentsMargins(0, 0, 0, 0)
        self.__autoHideButton = QToolButton()
        self.__autoHideButton.setCheckable(True)
        self.__autoHideButton.setIcon(
            UI.PixmapCache.getIcon("autoHideOff.png"))
        self.__autoHideButton.setChecked(True)
        self.__autoHideButton.setToolTip(
            self.tr("Deselect to activate automatic collapsing"))
        self.barLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.barLayout.setContentsMargins(0, 0, 0, 0)
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.barLayout.addWidget(self.__autoHideButton)
        self.barLayout.addWidget(self.__tabBar)
        self.layout.addLayout(self.barLayout)
        self.layout.addWidget(self.__stackedWidget)
        self.setLayout(self.layout)
        
        # initialize the delay timer
        self.__actionMethod = None
        self.__delayTimer = QTimer(self)
        self.__delayTimer.setSingleShot(True)
        self.__delayTimer.setInterval(delay)
        self.__delayTimer.timeout.connect(self.__delayedAction)
        
        self.__minimized = False
        self.__minSize = 0
        self.__maxSize = 0
        self.__bigSize = QSize()
        
        self.splitter = None
        self.splitterSizes = []
        
        self.__hasFocus = False
        # flag storing if this widget or any child has the focus
        self.__autoHide = False
        
        self.__tabBar.installEventFilter(self)
        
        self.__orientation = E5SideBar.North
        if orientation is None:
            orientation = E5SideBar.North
        self.setOrientation(orientation)
        
        self.__tabBar.currentChanged[int].connect(
            self.__stackedWidget.setCurrentIndex)
        e5App().focusChanged[QWidget, QWidget].connect(self.__appFocusChanged)
        self.__autoHideButton.toggled[bool].connect(self.__autoHideToggled)
    
    def setSplitter(self, splitter):
        """
        Public method to set the splitter managing the sidebar.
        
        @param splitter reference to the splitter (QSplitter)
        """
        self.splitter = splitter
        self.splitter.splitterMoved.connect(self.__splitterMoved)
        self.splitter.setChildrenCollapsible(False)
        index = self.splitter.indexOf(self)
        self.splitter.setCollapsible(index, False)
    
    def __splitterMoved(self, pos, index):
        """
        Private slot to react on splitter moves.
        
        @param pos new position of the splitter handle (integer)
        @param index index of the splitter handle (integer)
        """
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()
    
    def __delayedAction(self):
        """
        Private slot to handle the firing of the delay timer.
        """
        if self.__actionMethod is not None:
            self.__actionMethod()
    
    def setDelay(self, delay):
        """
        Public method to set the delay value for the expand/shrink delay in
        milliseconds.
        
        @param delay value for the expand/shrink delay in milliseconds
            (integer)
        """
        self.__delayTimer.setInterval(delay)
    
    def delay(self):
        """
        Public method to get the delay value for the expand/shrink delay in
        milliseconds.
        
        @return value for the expand/shrink delay in milliseconds (integer)
        """
        return self.__delayTimer.interval()
    
    def __cancelDelayTimer(self):
        """
        Private method to cancel the current delay timer.
        """
        self.__delayTimer.stop()
        self.__actionMethod = None
    
    def shrink(self):
        """
        Public method to record a shrink request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__shrinkIt
        self.__delayTimer.start()
   
    def __shrinkIt(self):
        """
        Private method to shrink the sidebar.
        """
        self.__minimized = True
        self.__bigSize = self.size()
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
            self.__maxSize = self.maximumHeight()
        else:
            self.__minSize = self.minimumSizeHint().width()
            self.__maxSize = self.maximumWidth()
        if self.splitter:
            self.splitterSizes = self.splitter.sizes()
        
        self.__stackedWidget.hide()
        
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.setFixedHeight(self.__tabBar.minimumSizeHint().height())
        else:
            self.setFixedWidth(self.__tabBar.minimumSizeHint().width())
        
        self.__actionMethod = None
    
    def expand(self):
        """
        Public method to record a expand request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__expandIt
        self.__delayTimer.start()
    
    def __expandIt(self):
        """
        Private method to expand the sidebar.
        """
        self.__minimized = False
        self.__stackedWidget.show()
        self.resize(self.__bigSize)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = max(self.__minSize, self.minimumSizeHint().height())
            self.setMinimumHeight(minSize)
            self.setMaximumHeight(self.__maxSize)
        else:
            minSize = max(self.__minSize, self.minimumSizeHint().width())
            self.setMinimumWidth(minSize)
            self.setMaximumWidth(self.__maxSize)
        if self.splitter:
            self.splitter.setSizes(self.splitterSizes)
        
        self.__actionMethod = None
    
    def isMinimized(self):
        """
        Public method to check the minimized state.
        
        @return flag indicating the minimized state (boolean)
        """
        return self.__minimized
    
    def isAutoHiding(self):
        """
        Public method to check, if the auto hide function is active.
        
        @return flag indicating the state of auto hiding (boolean)
        """
        return self.__autoHide
    
    def eventFilter(self, obj, evt):
        """
        Public method to handle some events for the tabbar.
        
        @param obj reference to the object (QObject)
        @param evt reference to the event object (QEvent)
        @return flag indicating, if the event was handled (boolean)
        """
        if obj == self.__tabBar:
            if evt.type() == QEvent.MouseButtonPress:
                pos = evt.pos()
                for i in range(self.__tabBar.count()):
                    if self.__tabBar.tabRect(i).contains(pos):
                        break
                
                if i == self.__tabBar.currentIndex():
                    if self.isMinimized():
                        self.expand()
                    else:
                        self.shrink()
                    return True
                elif self.isMinimized():
                    self.expand()
            elif evt.type() == QEvent.Wheel:
                if qVersion() >= "5.0.0":
                    delta = evt.angleDelta().y()
                else:
                    delta = evt.delta()
                if delta > 0:
                    self.prevTab()
                else:
                    self.nextTab()
                return True
        
        return QWidget.eventFilter(self, obj, evt)
    
    def addTab(self, widget, iconOrLabel, label=None):
        """
        Public method to add a tab to the sidebar.
        
        @param widget reference to the widget to add (QWidget)
        @param iconOrLabel reference to the icon or the label text of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.addTab(iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.addTab(iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.addWidget(widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def insertTab(self, index, widget, iconOrLabel, label=None):
        """
        Public method to insert a tab into the sidebar.
        
        @param index the index to insert the tab at (integer)
        @param widget reference to the widget to insert (QWidget)
        @param iconOrLabel reference to the icon or the labeltext of the tab
            (QIcon, string)
        @param label the labeltext of the tab (string) (only to be
            used, if the second parameter is a QIcon)
        """
        if label:
            index = self.__tabBar.insertTab(index, iconOrLabel, label)
            self.__tabBar.setTabToolTip(index, label)
        else:
            index = self.__tabBar.insertTab(index, iconOrLabel)
            self.__tabBar.setTabToolTip(index, iconOrLabel)
        self.__stackedWidget.insertWidget(index, widget)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def removeTab(self, index):
        """
        Public method to remove a tab.
        
        @param index the index of the tab to remove (integer)
        """
        self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
        self.__tabBar.removeTab(index)
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            self.__minSize = self.minimumSizeHint().height()
        else:
            self.__minSize = self.minimumSizeHint().width()
    
    def clear(self):
        """
        Public method to remove all tabs.
        """
        while self.count() > 0:
            self.removeTab(0)
    
    def prevTab(self):
        """
        Public slot used to show the previous tab.
        """
        ind = self.currentIndex() - 1
        if ind == -1:
            ind = self.count() - 1
            
        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()
    
    def nextTab(self):
        """
        Public slot used to show the next tab.
        """
        ind = self.currentIndex() + 1
        if ind == self.count():
            ind = 0
            
        self.setCurrentIndex(ind)
        self.currentWidget().setFocus()
    
    def count(self):
        """
        Public method to get the number of tabs.
        
        @return number of tabs in the sidebar (integer)
        """
        return self.__tabBar.count()
    
    def currentIndex(self):
        """
        Public method to get the index of the current tab.
        
        @return index of the current tab (integer)
        """
        return self.__stackedWidget.currentIndex()
    
    def setCurrentIndex(self, index):
        """
        Public slot to set the current index.
        
        @param index the index to set as the current index (integer)
        """
        self.__tabBar.setCurrentIndex(index)
        self.__stackedWidget.setCurrentIndex(index)
        if self.isMinimized():
            self.expand()
    
    def currentWidget(self):
        """
        Public method to get a reference to the current widget.
        
        @return reference to the current widget (QWidget)
        """
        return self.__stackedWidget.currentWidget()
    
    def setCurrentWidget(self, widget):
        """
        Public slot to set the current widget.
        
        @param widget reference to the widget to become the current widget
            (QWidget)
        """
        self.__stackedWidget.setCurrentWidget(widget)
        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
        if self.isMinimized():
            self.expand()
    
    def indexOf(self, widget):
        """
        Public method to get the index of the given widget.
        
        @param widget reference to the widget to get the index of (QWidget)
        @return index of the given widget (integer)
        """
        return self.__stackedWidget.indexOf(widget)
    
    def isTabEnabled(self, index):
        """
        Public method to check, if a tab is enabled.
        
        @param index index of the tab to check (integer)
        @return flag indicating the enabled state (boolean)
        """
        return self.__tabBar.isTabEnabled(index)
    
    def setTabEnabled(self, index, enabled):
        """
        Public method to set the enabled state of a tab.
        
        @param index index of the tab to set (integer)
        @param enabled enabled state to set (boolean)
        """
        self.__tabBar.setTabEnabled(index, enabled)
    
    def orientation(self):
        """
        Public method to get the orientation of the sidebar.
        
        @return orientation of the sidebar (North, East, South, West)
        """
        return self.__orientation
    
    def setOrientation(self, orient):
        """
        Public method to set the orientation of the sidebar.

        @param orient orientation of the sidebar (North, East, South, West)
        """
        if orient == E5SideBar.North:
            self.__tabBar.setShape(QTabBar.RoundedNorth)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Expanding, QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.East:
            self.__tabBar.setShape(QTabBar.RoundedEast)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Preferred, QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.RightToLeft)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        elif orient == E5SideBar.South:
            self.__tabBar.setShape(QTabBar.RoundedSouth)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Expanding, QSizePolicy.Preferred)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.BottomToTop)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == E5SideBar.West:
            self.__tabBar.setShape(QTabBar.RoundedWest)
            self.__tabBar.setSizePolicy(
                QSizePolicy.Preferred, QSizePolicy.Expanding)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        self.__orientation = orient
    
    def tabIcon(self, index):
        """
        Public method to get the icon of a tab.
        
        @param index index of the tab (integer)
        @return icon of the tab (QIcon)
        """
        return self.__tabBar.tabIcon(index)
    
    def setTabIcon(self, index, icon):
        """
        Public method to set the icon of a tab.
        
        @param index index of the tab (integer)
        @param icon icon to be set (QIcon)
        """
        self.__tabBar.setTabIcon(index, icon)
    
    def tabText(self, index):
        """
        Public method to get the text of a tab.
        
        @param index index of the tab (integer)
        @return text of the tab (string)
        """
        return self.__tabBar.tabText(index)
    
    def setTabText(self, index, text):
        """
        Public method to set the text of a tab.
        
        @param index index of the tab (integer)
        @param text text to set (string)
        """
        self.__tabBar.setTabText(index, text)
    
    def tabToolTip(self, index):
        """
        Public method to get the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @return tooltip text of the tab (string)
        """
        return self.__tabBar.tabToolTip(index)
    
    def setTabToolTip(self, index, tip):
        """
        Public method to set the tooltip text of a tab.
        
        @param index index of the tab (integer)
        @param tip tooltip text to set (string)
        """
        self.__tabBar.setTabToolTip(index, tip)
    
    def tabWhatsThis(self, index):
        """
        Public method to get the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @return WhatsThis text of the tab (string)
        """
        return self.__tabBar.tabWhatsThis(index)
    
    def setTabWhatsThis(self, index, text):
        """
        Public method to set the WhatsThis text of a tab.
        
        @param index index of the tab (integer)
        @param text WhatsThis text to set (string)
        """
        self.__tabBar.setTabWhatsThis(index, text)
    
    def widget(self, index):
        """
        Public method to get a reference to the widget associated with a tab.
        
        @param index index of the tab (integer)
        @return reference to the widget (QWidget)
        """
        return self.__stackedWidget.widget(index)
    
    def saveState(self):
        """
        Public method to save the state of the sidebar.
        
        @return saved state as a byte array (QByteArray)
        """
        if len(self.splitterSizes) == 0:
            if self.splitter:
                self.splitterSizes = self.splitter.sizes()
            self.__bigSize = self.size()
            if self.__orientation in [E5SideBar.North, E5SideBar.South]:
                self.__minSize = self.minimumSizeHint().height()
                self.__maxSize = self.maximumHeight()
            else:
                self.__minSize = self.minimumSizeHint().width()
                self.__maxSize = self.maximumWidth()
        
        data = QByteArray()
        stream = QDataStream(data, QIODevice.WriteOnly)
        stream.setVersion(QDataStream.Qt_4_6)
        
        stream.writeUInt16(self.Version)
        stream.writeBool(self.__minimized)
        stream << self.__bigSize
        stream.writeUInt16(self.__minSize)
        stream.writeUInt16(self.__maxSize)
        stream.writeUInt16(len(self.splitterSizes))
        for size in self.splitterSizes:
            stream.writeUInt16(size)
        stream.writeBool(self.__autoHide)
        
        return data
    
    def restoreState(self, state):
        """
        Public method to restore the state of the sidebar.
        
        @param state byte array containing the saved state (QByteArray)
        @return flag indicating success (boolean)
        """
        if state.isEmpty():
            return False
        
        if self.__orientation in [E5SideBar.North, E5SideBar.South]:
            minSize = self.layout.minimumSize().height()
            maxSize = self.maximumHeight()
        else:
            minSize = self.layout.minimumSize().width()
            maxSize = self.maximumWidth()
        
        data = QByteArray(state)
        stream = QDataStream(data, QIODevice.ReadOnly)
        stream.setVersion(QDataStream.Qt_4_6)
        stream.readUInt16()  # version
        minimized = stream.readBool()
        
        if minimized and not self.__minimized:
            self.shrink()
        
        stream >> self.__bigSize
        self.__minSize = max(stream.readUInt16(), minSize)
        self.__maxSize = max(stream.readUInt16(), maxSize)
        count = stream.readUInt16()
        self.splitterSizes = []
        for i in range(count):
            self.splitterSizes.append(stream.readUInt16())
        
        self.__autoHide = stream.readBool()
        self.__autoHideButton.setChecked(not self.__autoHide)
        
        if not minimized:
            self.expand()
        
        return True
    
    #######################################################################
    ## methods below implement the autohide functionality
    #######################################################################
    
    def __autoHideToggled(self, checked):
        """
        Private slot to handle the toggling of the autohide button.
        
        @param checked flag indicating the checked state of the button
            (boolean)
        """
        self.__autoHide = not checked
        if self.__autoHide:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOn.png"))
        else:
            self.__autoHideButton.setIcon(
                UI.PixmapCache.getIcon("autoHideOff.png"))
    
    def __appFocusChanged(self, old, now):
        """
        Private slot to handle a change of the focus.
        
        @param old reference to the widget, that lost focus (QWidget or None)
        @param now reference to the widget having the focus (QWidget or None)
        """
        self.__hasFocus = self.isAncestorOf(now)
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        elif self.__autoHide and self.__hasFocus and self.isMinimized():
            self.expand()
    
    def enterEvent(self, event):
        """
        Protected method to handle the mouse entering this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and self.isMinimized():
            self.expand()
        else:
            self.__cancelDelayTimer()
    
    def leaveEvent(self, event):
        """
        Protected method to handle the mouse leaving this widget.
        
        @param event reference to the event (QEvent)
        """
        if self.__autoHide and not self.__hasFocus and not self.isMinimized():
            self.shrink()
        else:
            self.__cancelDelayTimer()
    
    def shutdown(self):
        """
        Public method to shut down the object.
        
        This method does some preparations so the object can be deleted
        properly. It disconnects from the focusChanged signal in order to
        avoid trouble later on.
        """
        e5App().focusChanged[QWidget, QWidget].disconnect(
            self.__appFocusChanged)
Пример #35
0
class Posttid(QMainWindow):
    """
    The main application window and functions which apply to all windows.
    """

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

        # Set up the main window ui including parameters such as window size and global font
        self.set_up_window()

        # Load in the saved email and requests
        self.data, self.email, self.requests = self.load()

        # Set up each individual window screen
        self.central_widget = QStackedWidget()
        self.settings_widget = SettingsWindow(self.email, self.requests, parent=self)
        self.status_widget = StatusWindow(parent=self)
        self.central_widget.addWidget(self.status_widget)
        self.central_widget.addWidget(self.settings_widget)
        self.setCentralWidget(self.central_widget)

        # Start a new background thread to run the requests
        self.worker = Worker()
        self.worker.set_values(self.email, self.requests)
        self.worker.missing_email_signal.connect(self.log.missing_email)
        self.worker.connect_signal.connect(self.log.connection)
        self.worker.reconnect_signal.connect(self.log.reconnect)
        self.worker.request_signal.connect(self.log.request_found)
        self.worker.connectionerror_signal.connect(self.log.no_connection)
        self.worker.subreddit_noexist_signal.connect(self.log.subreddit_noexists)
        self.worker.status_condition_signal.connect(self.status_widget.set_status)
        self.worker.timeout_signal.connect(self.log.timeout)
        self.worker.httperror_signal.connect(self.log.http)
        self.worker.test_inside_loop.connect(self.log.inside_loop)
        self.worker.test_query_requests.connect(self.log.query_requests)
        self.worker.start()

        # Stop the worker thread when accessing the settings window
        self.status_widget.settings.clicked.connect(self.worker.terminate)

    def set_up_window(self):
        """ Defines the features for the status window """

        self.setWindowTitle("Posttid")

        font = QFont()
        font.setPointSize(10)
        self.setFont(font)

        self.resize(450, 300)

        self.move(QApplication.desktop().screen().rect().center() - self.rect().center())

    def switch_layout_status(self):
        """ Switches from the settings window to the status window """
        self.central_widget.setCurrentIndex(0)
        self.status_widget.status_disable_checkbox.setChecked(self.settings_widget.settings_disable_checkbox
                                                              .isChecked())

    def switch_layout_settings(self):
        """ Switches from the status window to the settings window """
        self.central_widget.setCurrentIndex(1)
        self.settings_widget.settings_disable_checkbox.setChecked(self.status_widget.status_disable_checkbox
                                                                  .isChecked())

    def link(self, link_string):
        QDesktopServices.openUrl(QUrl(link_string))

    @staticmethod
    def load():
        """
        Load in saved email and requests on start.
        :return: dictionary containing saved data or null if no saved data
        """
        try:
            with open(getcwd() + '/tkl.pkl', 'rb') as f:
                data = pickle.load(f)
                email = data["email"]
                requests = data["requests"]
                return data, email, requests
        except IOError:
            return {}, "", {}
Пример #36
0
class AppSettings(QDialog):

    SettingsWidgets = []

    def __init__(self, conf, **kwargs):
        super().__init__(**kwargs)

        self.conf = conf
        self.setWindowTitle('LiSP preferences')

        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMaximumSize(635, 530)
        self.setMinimumSize(635, 530)
        self.resize(635, 530)

        self.listWidget = QListWidget(self)
        self.listWidget.setGeometry(QtCore.QRect(5, 10, 185, 470))

        self.sections = QStackedWidget(self)
        self.sections.setGeometry(QtCore.QRect(200, 10, 430, 470))

        for widget in self.SettingsWidgets:
            widget = widget(QtCore.QSize(430, 465), self)
            widget.set_configuration(self.conf)

            self.listWidget.addItem(widget.NAME)
            self.sections.addWidget(widget)

        if len(self.SettingsWidgets) > 0:
            self.listWidget.setCurrentRow(0)

        self.listWidget.currentItemChanged.connect(self._change_page)

        self.dialogButtons = QDialogButtonBox(self)
        self.dialogButtons.setGeometry(10, 495, 615, 30)
        self.dialogButtons.setStandardButtons(QDialogButtonBox.Cancel |
                                              QDialogButtonBox.Ok)

        self.dialogButtons.rejected.connect(self.reject)
        self.dialogButtons.accepted.connect(self.accept)

    def get_configuraton(self):
        conf = {}

        for n in range(self.sections.count()):
            widget = self.sections.widget(n)
            newconf = widget.get_configuration()
            deep_update(conf, newconf)

        return conf

    @classmethod
    def register_settings_widget(cls, widget):
        if widget not in cls.SettingsWidgets:
            cls.SettingsWidgets.append(widget)

    @classmethod
    def unregister_settings_widget(cls, widget):
        if widget not in cls.SettingsWidgets:
            cls.SettingsWidgets.remove(widget)

    def _change_page(self, current, previous):
        if not current:
            current = previous

        self.sections.setCurrentIndex(self.listWidget.row(current))
Пример #37
0
class FilterDialog(QDialog):

    def __init__(self, parent=None):
        super(FilterDialog, self).__init__(parent)

        self.accepted.connect(self.createFilter)

        self.contentsWidget = QListWidget()
        self.contentsWidget.setViewMode(QListView.IconMode)
        self.contentsWidget.setIconSize(QSize(96, 84))
        self.contentsWidget.setMovement(QListView.Static)
        self.contentsWidget.setMaximumWidth(128)
        self.contentsWidget.setSpacing(12)

        self.basicFilterPage = BasicFilterPage()
        self.timeFilterPage = DateTimeFilterPage()
        self.locationFilterPage = LocationFilterPage()

        self.pagesWidget = QStackedWidget()
        self.pagesWidget.addWidget(self.basicFilterPage)
        self.pagesWidget.addWidget(self.timeFilterPage)
        self.pagesWidget.addWidget(self.locationFilterPage)
        self.pagesWidget.setMinimumHeight(360)

        rejectButton = QPushButton("Storno")
        rejectButton.clicked.connect(self.reject)
        acceptButton = QPushButton("OK")
        acceptButton.clicked.connect(self.accept)

        self.createIcons()
        self.contentsWidget.setCurrentRow(0)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.contentsWidget)
        horizontalLayout.addWidget(self.pagesWidget, 1)

        buttonsLayout = QHBoxLayout()
        buttonsLayout.addStretch(1)
        buttonsLayout.addWidget(acceptButton)
        buttonsLayout.addWidget(rejectButton)

        layout = QVBoxLayout()
        layout.addLayout(horizontalLayout)
        layout.addStretch(1)
        layout.addSpacing(12)
        layout.addLayout(buttonsLayout)

        self.setLayout(layout)

        self.setMinimumWidth(450)
        self.setWindowTitle("Filtrování výsledků")

    def initControls(self, options, filter_):
        self.basicFilterPage.initControls(options, filter_)
        self.timeFilterPage.initControls(filter_)
        self.locationFilterPage.initControls(filter_)

    def changePage(self, current, previous):
        if not current:
            current = previous

        self.pagesWidget.setCurrentIndex(self.contentsWidget.row(current))

    def createIcons(self):
        basicButton = QListWidgetItem(self.contentsWidget)
        basicButton.setIcon(QIcon('app/ui/images/settings.png'))
        basicButton.setText("Základní filtry")
        basicButton.setTextAlignment(Qt.AlignHCenter)
        basicButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        timeButton = QListWidgetItem(self.contentsWidget)
        timeButton.setIcon(QIcon('app/ui/images/time.png'))
        timeButton.setText("Datum a čas")
        timeButton.setTextAlignment(Qt.AlignHCenter)
        timeButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        locationButton = QListWidgetItem(self.contentsWidget)
        locationButton.setIcon(QIcon('app/ui/images/location.png'))
        locationButton.setText("Lokace")
        locationButton.setTextAlignment(Qt.AlignHCenter)
        locationButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        self.contentsWidget.currentItemChanged.connect(self.changePage)

    @pyqtSlot()
    def createFilter(self):
        self._filter = self.basicFilterPage.getFilter()
        self._filter.update(self.timeFilterPage.getFilter())
        self._filter.update(self.locationFilterPage.getFilter())

    def filter(self):
        return self._filter
Пример #38
0
class ConfigDialog(QDialog):
    def __init__(self, parent=None):
        super(ConfigDialog, self).__init__(parent)

        self.contentsWidget = QListWidget()
        self.contentsWidget.setViewMode(QListView.IconMode)
        self.contentsWidget.setIconSize(QSize(96, 84))
        self.contentsWidget.setMovement(QListView.Static)
        self.contentsWidget.setMaximumWidth(128)
        self.contentsWidget.setSpacing(12)

        self.pagesWidget = QStackedWidget()
        self.pagesWidget.addWidget(ConfigurationPage())
        self.pagesWidget.addWidget(UpdatePage())
        self.pagesWidget.addWidget(QueryPage())

        closeButton = QPushButton("Close")

        self.createIcons()
        self.contentsWidget.setCurrentRow(0)

        closeButton.clicked.connect(self.close)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.contentsWidget)
        horizontalLayout.addWidget(self.pagesWidget, 1)

        buttonsLayout = QHBoxLayout()
        buttonsLayout.addStretch(1)
        buttonsLayout.addWidget(closeButton)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(horizontalLayout)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(12)
        mainLayout.addLayout(buttonsLayout)

        self.setLayout(mainLayout)

        self.setWindowTitle("Config Dialog")

    def changePage(self, current, previous):
        if not current:
            current = previous

        self.pagesWidget.setCurrentIndex(self.contentsWidget.row(current))

    def createIcons(self):
        configButton = QListWidgetItem(self.contentsWidget)
        configButton.setIcon(QIcon(':/images/config.png'))
        configButton.setText("Configuration")
        configButton.setTextAlignment(Qt.AlignHCenter)
        configButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        updateButton = QListWidgetItem(self.contentsWidget)
        updateButton.setIcon(QIcon(':/images/update.png'))
        updateButton.setText("Update")
        updateButton.setTextAlignment(Qt.AlignHCenter)
        updateButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        queryButton = QListWidgetItem(self.contentsWidget)
        queryButton.setIcon(QIcon(':/images/query.png'))
        queryButton.setText("Query")
        queryButton.setTextAlignment(Qt.AlignHCenter)
        queryButton.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        self.contentsWidget.currentItemChanged.connect(self.changePage)
Пример #39
0
class TableWidget(QSplitter):

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

        # vbox = QVBoxLayout(self)
        # vbox.setContentsMargins(0, 0, 0, 0)

        self._tabs = QTabWidget()
        self._tabs.setAutoFillBackground(True)
        p = self._tabs.palette()
        p.setColor(p.Window, QColor("white"))
        self._tabs.setPalette(p)
        self._other_tab = QTabWidget()
        self._other_tab.setAutoFillBackground(True)
        self._other_tab.setPalette(p)
        self.addWidget(self._tabs)
        self.addWidget(self._other_tab)
        self.setSizes([1, 1])
        self._other_tab.hide()

        self.relations = {}

        # Stack
        self.stacked = QStackedWidget()
        self._tabs.addTab(self.stacked, "Workspace")
        self.stacked_result = QStackedWidget()
        self._tabs.addTab(self.stacked_result, self.tr("Resultados"))

        btn_split = QToolButton()
        btn_split.setToolTip(self.tr("Click para dividir la pantalla"))
        btn_split.setAutoRaise(True)
        btn_split.setIcon(QIcon(":img/split"))
        self._tabs.setCornerWidget(btn_split)
        btn_split.clicked.connect(self._split)
        btn_split = QToolButton()
        btn_split.setToolTip(self.tr("Click para juntar las pantallas"))
        btn_split.setAutoRaise(True)
        btn_split.setIcon(QIcon(":img/split"))
        btn_split.clicked.connect(self._unsplit)
        self._other_tab.setCornerWidget(btn_split)
        # self.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.customContextMenuRequested.connect(self._show_menu)

        lateral_widget = Pireal.get_service("lateral_widget")
        lateral_widget.resultClicked.connect(self._on_result_list_clicked)
        lateral_widget.resultSelectionChanged.connect(
            lambda index: self.stacked_result.setCurrentIndex(index))
        # lateral_widget.newRowsRequested.connect(self._insert_rows)

    def insert_rows(self, tuplas):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            for tupla in tuplas:
                model.insertRow(model.rowCount(), tupla)
        current_view.adjust_columns()

    def _on_result_list_clicked(self, index):
        self.stacked_result.setCurrentIndex(index)
        if not self._other_tab.isVisible():
            self._tabs.setCurrentIndex(1)

    def _unsplit(self):
        self._other_tab.hide()
        result_widget = self._other_tab.widget(0)
        self._tabs.addTab(result_widget, self.tr("Resultados"))
        self._tabs.cornerWidget().show()

    def _split(self):
        result_widget = self._tabs.widget(1)
        self._other_tab.addTab(result_widget, self.tr("Resultados"))
        self._other_tab.show()
        self.setSizes([1, 1])
        self._tabs.cornerWidget().hide()
        self.setOrientation(Qt.Horizontal)

    def _show_menu(self, position):
        menu = QMenu(self)

        if self.count() > 0:
            add_tuple_action = menu.addAction(self.tr("Agregar Tupla"))
            add_col_action = menu.addAction(self.tr("Add Column"))

            add_tuple_action.triggered.connect(self.add_tuple)
            add_col_action.triggered.connect(self.add_column)
            menu.addSeparator()

        add_relation_action = menu.addAction(self.tr("Create new Relation"))
        add_relation_action.triggered.connect(self.__new_relation)

        menu.exec_(self.mapToGlobal(position))

    def __new_relation(self):
        central_service = Pireal.get_service("central")
        central_service.create_new_relation()

    def count(self):
        return self.stacked.count()

    def remove_table(self, index):
        widget = self.stacked.widget(index)
        self.stacked.removeWidget(widget)
        del widget

    def current_table(self):
        return self.stacked.currentWidget()

    def remove_relation(self, name):
        del self.relations[name]

    def add_relation(self, name, rela):
        if self.relations.get(name, None) is None:
            self.relations[name] = rela
            return True
        return False

    def add_table(self, rela, name, table):
        """ Add new table from New Relation Dialog """

        self.add_relation(name, rela)
        self.stacked.addWidget(table)

    def add_tuple(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            model.insertRow(model.rowCount())

    def add_column(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            model.insertColumn(model.columnCount())

    def delete_tuple(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            selection = current_view.selectionModel()
            if selection.hasSelection():
                selection = selection.selection()
                rows = set([index.row() for index in selection.indexes()])
                rows = sorted(list(rows))
                previous = -1
                i = len(rows) - 1
                while i >= 0:
                    current = rows[i]
                    if current != previous:
                        model.removeRow(current)
                    i -= 1

    def delete_column(self):
        """ Elimina la/las columnas seleccionadas """

        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            selection = current_view.selectionModel()
            if selection.hasSelection():
                selection = selection.selection()
                columns = set(
                    [index.column() for index in selection.indexes()])
                columns = sorted(list(columns))
                previous = -1
                i = len(columns) - 1
                while i >= 0:
                    current = columns[i]
                    if current != previous:
                        model.removeColumn(current)
                    i -= 1

    def create_table(self, rela, editable=True):
        """ Se crea la vista y el modelo """

        _view = view.View()
        _model = model.Model(rela)
        if not editable:
            _model.editable = False
        _view.setModel(_model)
        _view.setItemDelegate(delegate.Delegate())
        _view.setHorizontalHeader(view.Header())
        return _view
Пример #40
0
class QChatTab(QWidget):

    def __init__(self, chat_window, nick=None, just_accepted=False):
        QWidget.__init__(self)

        self.chat_window = chat_window
        self.nick = nick
        self.just_accepted = just_accepted
        self.unread_count = 0

        self.widget_stack = QStackedWidget(self)
        self.widget_stack.addWidget(QNickInputWidget('new_chat.png', 150, self.connectClicked, parent=self))
        self.widget_stack.addWidget(QConnectingWidget(parent=self))
        self.widget_stack.addWidget(QChatWidget(self.chat_window, nick=nick, parent=self))

        if self.nick is not None:
            self.widget_stack.setCurrentIndex(2)
        else:
            self.widget_stack.setCurrentIndex(0)

        layout = QHBoxLayout()
        layout.addWidget(self.widget_stack)
        self.setLayout(layout)

    def connectClicked(self, nick):
        if self.chat_window.isNickInTabs(nick):
            QMessageBox.warning(self, TITLE_ALREADY_CONNECTED, ALREADY_CONNECTED % (nick))
            return

        self.nick = nick
        self.widget_stack.widget(1).setConnectingToNick(self.nick)
        self.widget_stack.setCurrentIndex(1)
        self.chat_window.client.openSession(self.nick)
        self.widget_stack.widget(2).setRemoteNick(self.nick)

    def appendMessage(self, message, source):
        self.widget_stack.widget(2).appendMessage(message, source)

    def showNowChattingMessage(self):
        self.widget_stack.setCurrentIndex(2)
        self.widget_stack.widget(2).showNowChattingMessage(self.nick)

    def enable(self):
        self.widget_stack.setCurrentIndex(2)
        self.widget_stack.widget(2).enable()

    def resetOrDisable(self):
        cur_widget_index = self.widget_stack.currentIndex()
        if cur_widget_index == 1:
            self.widget_stack.setCurrentIndex(0)
        elif cur_widget_index == 2:
            self.widget_stack.widget(2).disable()
Пример #41
0
class CentralWidget(QWidget):
    # This signals is used by notificator
    databaseSaved = pyqtSignal('QString')
    querySaved = pyqtSignal('QString')

    def __init__(self):
        QWidget.__init__(self)
        box = QVBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)
        box.setSpacing(0)

        self.stacked = QStackedWidget()
        box.addWidget(self.stacked)

        self.created = False
        self.__last_open_folder = None
        self.__recent_dbs = []
        if PSetting.RECENT_DBS:
            self.__recent_dbs = PSetting.RECENT_DBS

        Pireal.load_service("central", self)

    @property
    def recent_databases(self):
        return self.__recent_dbs

    @recent_databases.setter
    def recent_databases(self, database_file):
        if database_file in PSetting.RECENT_DBS:
            PSetting.RECENT_DBS.remove(database_file)
        PSetting.RECENT_DBS.insert(0, database_file)
        self.__recent_dbs = PSetting.RECENT_DBS

    def create_database(self):
        """ Show a wizard widget to create a new database,
        only have one database open at time.
        """

        if self.created:
            QMessageBox.information(self,
                                    self.tr("Information"),
                                    self.tr("You may only have one database"
                                            " open at time."))
            DEBUG("Ya existe una base de datos abierta")
            return
        wizard = database_wizard.DatabaseWizard(self)
        wizard.wizardFinished.connect(
            self.__on_wizard_finished)
        # Hide menubar and toolbar
        pireal = Pireal.get_service("pireal")
        pireal.show_hide_menubar()
        pireal.show_hide_toolbar()
        # Add wizard widget to stacked
        self.add_widget(wizard)

    def __on_wizard_finished(self, data, wizard_widget):
        """ This slot execute when wizard to create a database is finished """

        pireal = Pireal.get_service("pireal")
        if not data:
            # If it's canceled, remove wizard widget and return to Start Page
            self.remove_last_widget()
        else:
            # Create a new data base container
            db_container = database_container.DatabaseContainer()
            # Associate the file name with the PFile object
            pfile_object = pfile.File(data['filename'])
            # Associate PFile object with data base container
            # and add widget to stacked
            db_container.pfile = pfile_object
            self.add_widget(db_container)
            # Remove wizard
            self.stacked.removeWidget(wizard_widget)
            # Set window title
            pireal.change_title(file_manager.get_basename(data['filename']))
            # Enable db actions
            pireal.set_enabled_db_actions(True)
            pireal.set_enabled_relation_actions(True)
            self.created = True
            DEBUG("Base de datos creada correctamente: '{}'".format(
                data['filename']))

        # If data or not, show menubar and toolbar again
        pireal.show_hide_menubar()
        pireal.show_hide_toolbar()

    def open_database(self, filename=''):
        """ This function opens a database and set this on the UI """

        # If not filename provide, then open dialog to select
        if self.created:
            QMessageBox.information(self,
                                    self.tr("Information"),
                                    self.tr("You may only have one database"
                                            " open at time."))
            DEBUG("Ya existe una base de datos abierta")
            return
        if not filename:
            if self.__last_open_folder is None:
                directory = os.path.expanduser("~")
            else:
                directory = self.__last_open_folder
            filter_ = settings.SUPPORTED_FILES.split(';;')[0]
            filename, _ = QFileDialog.getOpenFileName(self,
                                                      self.tr("Open Database"),
                                                      directory,
                                                      filter_)
            # If is canceled, return
            if not filename:
                return

            # Remember the folder
            self.__last_open_folder = file_manager.get_path(filename)

        DEBUG("Abriendo la base de datos: '{}'".format(filename))

        # If filename provide
        try:
            # Read pdb file
            pfile_object = pfile.File(filename)
            db_data = pfile_object.read()
            # Create a dict to manipulate data more easy
            db_data = self.__sanitize_data(db_data)
        except Exception as reason:
            QMessageBox.information(self,
                                    self.tr("The file couldn't be open"),
                                    str(reason))
            CRITICAL("Error al intentar abrir el archivo: {}".format(reason))
            return

        # Create a database container widget
        db_container = database_container.DatabaseContainer()

        try:
            db_container.create_database(db_data)
        except Exception as reason:
            QMessageBox.information(self,
                                    self.tr("Error"),
                                    str(reason))
            CRITICAL("Error al crear la base de datos: {}".format(reason))
            return

        # Set the PFile object to the new database
        db_container.pfile = pfile_object
        # Add data base container to stacked
        self.add_widget(db_container)
        # Database name
        db_name = file_manager.get_basename(filename)
        # Update title with the new database name, and enable some actions
        pireal = Pireal.get_service("pireal")
        pireal.change_title(db_name)
        pireal.set_enabled_db_actions(True)
        pireal.set_enabled_relation_actions(True)
        # Add to recent databases
        self.recent_databases = filename
        self.created = True

    def open_query(self):
        filter_ = settings.SUPPORTED_FILES.split(';;')[1]
        filename, _ = QFileDialog.getOpenFileName(self,
                                                  self.tr("Open Query"),
                                                  os.path.expanduser("~"),
                                                  filter_)
        if not filename:
            return
        # FIXME: mejorar éste y new_query
        self.new_query(filename)

    def save_query(self, editor=None):
        db = self.get_active_db()
        fname = db.save_query(editor)
        if fname:
            self.querySaved.emit(self.tr("Query saved: {}".format(fname)))

    def save_query_as(self):
        pass

    def __sanitize_data(self, data):
        """
        This function converts the data into a dictionary
        for better handling then.
        The argument 'data' is the content of the database.
        """

        # FIXME: controlar cuando al final de la línea hay una coma
        data_dict = {'tables': []}

        for line_count, line in enumerate(data.splitlines()):
            # Ignore blank lines
            if not line:
                continue
            if line.startswith('@'):
                # This line is a header
                tpoint = line.find(':')
                if tpoint == -1:
                    raise Exception("Invalid syntax at line {}".format(
                        line_count + 1))

                table_name, line = line.split(':')
                table_name = table_name[1:].strip()

                table_dict = {}
                table_dict['name'] = table_name
                table_dict['header'] = line.split(',')
                table_dict['tuples'] = []
            else:
                for l in csv.reader([line]):
                    # Remove spaces
                    l = list(map(str.strip, l))
                    # FIXME: this is necesary?
                    if table_dict['name'] == table_name:
                        table_dict['tuples'].append(l)
            if not table_dict['tuples']:
                data_dict['tables'].append(table_dict)

        return data_dict

    def remove_last_widget(self):
        """ Remove last widget from stacked """

        widget = self.stacked.widget(self.stacked.count() - 1)
        self.stacked.removeWidget(widget)

    def close_database(self):
        """ Close the database and return to the main widget """

        db = self.get_active_db()
        query_container = db.query_container

        if db.modified:
            msgbox = QMessageBox(self)
            msgbox.setIcon(QMessageBox.Question)
            msgbox.setWindowTitle(self.tr("Save Changes?"))
            msgbox.setText(self.tr("The <b>{}</b> database has ben"
                                   " modified.<br>Do you want save "
                                   "your changes?".format(
                                       db.dbname())))
            cancel_btn = msgbox.addButton(self.tr("Cancel"),
                                          QMessageBox.RejectRole)
            msgbox.addButton(self.tr("No"),
                             QMessageBox.NoRole)
            yes_btn = msgbox.addButton(self.tr("Yes"),
                                       QMessageBox.YesRole)
            msgbox.exec_()
            r = msgbox.clickedButton()
            if r == cancel_btn:
                return
            if r == yes_btn:
                self.save_database()

        # Check if editor is modified
        query_widget = query_container.currentWidget()
        if query_widget is not None:
            weditor = query_widget.get_editor()
            if weditor is not None:
                # TODO: duplicate code, see tab widget
                if weditor.modified:
                    msgbox = QMessageBox(self)
                    msgbox.setIcon(QMessageBox.Question)
                    msgbox.setWindowTitle(self.tr("File modified"))
                    msgbox.setText(self.tr("The file <b>{}</b> has unsaved "
                                           "changes. You want to keep "
                                           "them?".format(
                                               weditor.name)))
                    cancel_btn = msgbox.addButton(self.tr("Cancel"),
                                                  QMessageBox.RejectRole)
                    msgbox.addButton(self.tr("No"),
                                     QMessageBox.NoRole)
                    yes_btn = msgbox.addButton(self.tr("Yes"),
                                               QMessageBox.YesRole)
                    msgbox.exec_()
                    r = msgbox.clickedButton()
                    if r == cancel_btn:
                        return
                    if r == yes_btn:
                        self.save_query(weditor)

        self.stacked.removeWidget(db)

        pireal = Pireal.get_service("pireal")
        pireal.set_enabled_db_actions(False)
        pireal.set_enabled_relation_actions(False)
        pireal.set_enabled_query_actions(False)
        pireal.set_enabled_editor_actions(False)
        self.created = False
        DEBUG("Se cerró la base de datos: '{}'".format(db.dbname()))
        del db

    def new_query(self, filename=''):
        pireal = Pireal.get_service("pireal")
        db_container = self.get_active_db()
        db_container.new_query(filename)
        # Enable editor actions
        # FIXME: refactoring
        pireal.set_enabled_query_actions(True)
        zoom_in_action = Pireal.get_action("zoom_in")
        zoom_in_action.setEnabled(True)
        zoom_out_action = Pireal.get_action("zoom_out")
        zoom_out_action.setEnabled(True)
        paste_action = Pireal.get_action("paste_action")
        paste_action.setEnabled(True)
        comment_action = Pireal.get_action("comment")
        comment_action.setEnabled(True)
        uncomment_action = Pireal.get_action("uncomment")
        uncomment_action.setEnabled(True)

    def execute_queries(self):
        db_container = self.get_active_db()
        db_container.execute_queries()

    def execute_selection(self):
        db_container = self.get_active_db()
        db_container.execute_selection()

    def save_database(self):

        db = self.get_active_db()
        if not db.modified:
            return

        # Get relations dict
        relations = db.table_widget.relations
        # Generate content
        content = file_manager.generate_database(relations)
        db.pfile.save(content=content)
        filename = db.pfile.filename
        # Emit signal
        self.databaseSaved.emit(
            self.tr("Database saved: {}".format(filename)))

        db.modified = False

    def save_database_as(self):
        filter = settings.SUPPORTED_FILES.split(';;')[0]
        filename, _ = QFileDialog.getSaveFileName(self,
                                                  self.tr("Save Database As"),
                                                  settings.PIREAL_PROJECTS,
                                                  filter)
        if not filename:
            return
        db = self.get_active_db()
        # Get relations
        relations = db.table_widget.relations
        # Content
        content = file_manager.generate_database(relations)
        db.pfile.save(content, filename)
        self.databaseSaved.emit(
            self.tr("Database saved: {}".format(db.pfile.filename)))

        db.modified = False

    def remove_relation(self):
        db = self.get_active_db()
        if db.delete_relation():
            db.modified = True

    def create_new_relation(self):
        data = new_relation_dialog.create_relation()
        if data is not None:
            db = self.get_active_db()
            rela, rela_name = data
            # Add table
            db.table_widget.add_table(rela, rela_name)
            # Add item to lateral widget
            db.lateral_widget.add_item(rela_name, rela.count())
            # Set modified db
            db.modified = True

    def edit_relation(self):
        db = self.get_active_db()
        lateral = db.lateral_widget
        selected_items = lateral.selectedItems()
        if selected_items:
            selected_relation = selected_items[0].text(0)
            relation_text = selected_relation.split()[0].strip()
            rela = db.table_widget.relations[relation_text]
            data = edit_relation_dialog.edit_relation(rela)
            if data is not None:
                # Update table
                db.table_widget.update_table(data)
                # Update relation
                db.table_widget.relations[relation_text] = data
                # Set modified db
                db.modified = True
                lateral.update_item(data.count())

    def load_relation(self, filename=''):
        """ Load Relation file """

        if not filename:
            if self.__last_open_folder is None:
                directory = os.path.expanduser("~")
            else:
                directory = self.__last_open_folder

            msg = self.tr("Open Relation File")
            filter_ = settings.SUPPORTED_FILES.split(';;')[-1]
            filenames = QFileDialog.getOpenFileNames(self, msg, directory,
                                                     filter_)[0]

            if not filenames:
                return

        # Save folder
        self.__last_open_folder = file_manager.get_path(filenames[0])
        db_container = self.get_active_db()
        if db_container.load_relation(filenames):
            db_container.modified = True

    def add_start_page(self):
        """ This function adds the Start Page to the stacked widget """

        sp = start_page.StartPage()
        self.add_widget(sp)

    def show_settings(self):
        """ Show settings dialog on stacked """

        preferences_dialog = preferences.Preferences(self)

        if isinstance(self.widget(1), preferences.Preferences):
            self.widget(1).close()
        else:
            self.stacked.insertWidget(1, preferences_dialog)
            self.stacked.setCurrentIndex(1)

        # Connect the closed signal
        preferences_dialog.settingsClosed.connect(self._settings_closed)

    def widget(self, index):
        """ Returns the widget at the given index """

        return self.stacked.widget(index)

    def add_widget(self, widget):
        """ Appends and show the given widget to the Stacked """

        index = self.stacked.addWidget(widget)
        self.stacked.setCurrentIndex(index)

    def _settings_closed(self):
        self.stacked.removeWidget(self.widget(1))
        self.stacked.setCurrentWidget(self.stacked.currentWidget())

    def get_active_db(self):
        """ Return an instance of DatabaseContainer widget if the
        stacked contains an DatabaseContainer in last index or None if it's
        not an instance of DatabaseContainer """

        index = self.stacked.count() - 1
        widget = self.widget(index)
        if isinstance(widget, database_container.DatabaseContainer):
            return widget
        return None

    def get_unsaved_queries(self):
        query_container = self.get_active_db().query_container
        return query_container.get_unsaved_queries()

    def undo_action(self):
        query_container = self.get_active_db().query_container
        query_container.undo()

    def redo_action(self):
        query_container = self.get_active_db().query_container
        query_container.redo()

    def cut_action(self):
        query_container = self.get_active_db().query_container
        query_container.cut()

    def copy_action(self):
        query_container = self.get_active_db().query_container
        query_container.copy()

    def paste_action(self):
        query_container = self.get_active_db().query_container
        query_container.paste()

    def zoom_in(self):
        query_container = self.get_active_db().query_container
        query_container.zoom_in()

    def zoom_out(self):
        query_container = self.get_active_db().query_container
        query_container.zoom_out()

    def comment(self):
        query_container = self.get_active_db().query_container
        query_container.comment()

    def uncomment(self):
        query_container = self.get_active_db().query_container
        query_container.uncomment()
Пример #42
0
class QueryWidget(QWidget):
    editorModified = pyqtSignal(bool)

    def __init__(self):
        super(QueryWidget, self).__init__()
        box = QVBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)

        self._vsplitter = QSplitter(Qt.Vertical)
        self._hsplitter = QSplitter(Qt.Horizontal)

        self._result_list = lateral_widget.LateralWidget()
        self._result_list.header().hide()
        self._hsplitter.addWidget(self._result_list)

        self._stack_tables = QStackedWidget()
        self._hsplitter.addWidget(self._stack_tables)

        self.relations = {}

        self._query_editor = editor.Editor()
        # Editor connections
        self._query_editor.customContextMenuRequested.connect(
            self.__show_context_menu)
        self._query_editor.modificationChanged[bool].connect(
            self.__editor_modified)
        self._query_editor.undoAvailable[bool].connect(
            self.__on_undo_available)
        self._query_editor.redoAvailable[bool].connect(
            self.__on_redo_available)
        self._query_editor.copyAvailable[bool].connect(
            self.__on_copy_available)
        self._vsplitter.addWidget(self._query_editor)

        self._vsplitter.addWidget(self._hsplitter)
        box.addWidget(self._vsplitter)

        # Connections
        self._result_list.itemClicked.connect(
            lambda index: self._stack_tables.setCurrentIndex(
                self._result_list.row()))
        self._result_list.itemDoubleClicked.connect(
            self.show_relation)

    def __show_context_menu(self, point):
        popup_menu = self._query_editor.createStandardContextMenu()

        undock_editor = QAction(self.tr("Undock"), self)
        popup_menu.insertAction(popup_menu.actions()[0],
                                undock_editor)
        popup_menu.insertSeparator(popup_menu.actions()[1])
        undock_editor.triggered.connect(self.__undock_editor)

        popup_menu.exec_(self.mapToGlobal(point))

    def __undock_editor(self):
        new_editor = editor.Editor()
        actual_doc = self._query_editor.document()
        new_editor.setDocument(actual_doc)
        new_editor.resize(900, 400)
        # Set text cursor
        tc = self._query_editor.textCursor()
        new_editor.setTextCursor(tc)
        # Set title
        db = Pireal.get_service("central").get_active_db()
        qc = db.query_container
        new_editor.setWindowTitle(qc.tab_text(qc.current_index()))
        new_editor.show()

    def __on_undo_available(self, value):
        """ Change state of undo action """

        pireal = Pireal.get_service("pireal")
        action = pireal.get_action("undo_action")
        action.setEnabled(value)

    def __on_redo_available(self, value):
        """ Change state of redo action """

        pireal = Pireal.get_service("pireal")
        action = pireal.get_action("redo_action")
        action.setEnabled(value)

    def __on_copy_available(self, value):
        """ Change states of cut and copy action """

        cut_action = Pireal.get_action("cut_action")
        cut_action.setEnabled(value)
        copy_action = Pireal.get_action("copy_action")
        copy_action.setEnabled(value)

    def show_relation(self, item):
        central_widget = Pireal.get_service("central")
        table_widget = central_widget.get_active_db().table_widget
        rela = self.relations[item.name]
        dialog = QDialog(self)
        dialog.resize(700, 500)
        dialog.setWindowTitle(item.name)
        box = QVBoxLayout(dialog)
        box.setContentsMargins(5, 5, 5, 5)
        table = table_widget.create_table(rela)
        box.addWidget(table)
        hbox = QHBoxLayout()
        btn = QPushButton(self.tr("Ok"))
        btn.clicked.connect(dialog.close)
        hbox.addStretch()
        hbox.addWidget(btn)
        box.addLayout(hbox)
        dialog.show()

    def save_sizes(self):
        """ Save sizes of Splitters """

        qsettings = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat)
        qsettings.setValue('hsplitter_query_sizes',
                           self._hsplitter.saveState())
        qsettings.setValue('vsplitter_query_sizes',
                           self._vsplitter.saveState())

    def get_editor(self):
        return self._query_editor

    def __editor_modified(self, modified):
        self.editorModified.emit(modified)

    def showEvent(self, event):
        super(QueryWidget, self).showEvent(event)
        self._hsplitter.setSizes([1, self.width() / 3])

    def clear_results(self):
        self._result_list.clear_items()
        i = self._stack_tables.count()
        while i >= 0:
            widget = self._stack_tables.widget(i)
            self._stack_tables.removeWidget(widget)
            if widget is not None:
                widget.deleteLater()
            i -= 1

    def add_table(self, rela, rname):
        wtable = custom_table.Table()
        # Model
        model = QStandardItemModel()
        wtable.setModel(model)
        model.setHorizontalHeaderLabels(rela.header)

        for data in rela.content:
            nrow = model.rowCount()
            # wtable.insertRow(nrow)
            for col, text in enumerate(data):
                item = QStandardItem(text)
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                model.setItem(nrow, col, item)

        index = self._stack_tables.addWidget(wtable)
        self._stack_tables.setCurrentIndex(index)

        self._result_list.add_item(rname, rela.count())
Пример #43
0
class EntryView(BaseTransactionView):
    def _setup(self):
        self._setupUi()
        self.etable = EntryTable(self.model.etable, view=self.tableView)
        self.efbar = EntryFilterBar(model=self.model.filter_bar, view=self.filterBar)
        self.bgraph = Chart(self.model.bargraph, view=self.barGraphView)
        self.lgraph = Chart(self.model.balgraph, view=self.lineGraphView)
        self._setupColumns() # Can only be done after the model has been connected

        self.reconciliationButton.clicked.connect(self.model.toggle_reconciliation_mode)

    def _setupUi(self):
        self.resize(483, 423)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setSpacing(0)
        self.filterBar = RadioBox(self)
        sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.filterBar.sizePolicy().hasHeightForWidth())
        self.filterBar.setSizePolicy(sizePolicy)
        self.horizontalLayout.addWidget(self.filterBar)
        self.horizontalLayout.addItem(horizontalSpacer())
        self.reconciliationButton = QPushButton(tr("Reconciliation"))
        self.reconciliationButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.reconciliationButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.splitterView = QSplitter()
        self.splitterView.setOrientation(Qt.Vertical)
        self.splitterView.setChildrenCollapsible(False)
        self.tableView = TableView(self)
        self.tableView.setAcceptDrops(True)
        self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed)
        self.tableView.setDragEnabled(True)
        self.tableView.setDragDropMode(QAbstractItemView.InternalMove)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setSortingEnabled(True)
        self.tableView.horizontalHeader().setHighlightSections(False)
        self.tableView.horizontalHeader().setMinimumSectionSize(18)
        self.tableView.verticalHeader().setVisible(False)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.splitterView.addWidget(self.tableView)
        self.graphView = QStackedWidget(self)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.graphView.sizePolicy().hasHeightForWidth())
        self.graphView.setSizePolicy(sizePolicy)
        self.graphView.setMinimumSize(0, 200)
        self.lineGraphView = LineGraphView()
        self.graphView.addWidget(self.lineGraphView)
        self.barGraphView = BarGraphView()
        self.graphView.addWidget(self.barGraphView)
        self.splitterView.addWidget(self.graphView)
        self.graphView.setCurrentIndex(1)
        self.splitterView.setStretchFactor(0, 1)
        self.splitterView.setStretchFactor(1, 0)
        self.verticalLayout.addWidget(self.splitterView)

    def _setupColumns(self):
        h = self.tableView.horizontalHeader()
        h.setSectionsMovable(True) # column drag & drop reorder

    # --- QWidget override
    def setFocus(self):
        self.etable.view.setFocus()

    # --- Public
    def fitViewsForPrint(self, viewPrinter):
        hidden = self.model.mainwindow.hidden_areas
        viewPrinter.fitTable(self.etable)
        if PaneArea.BottomGraph not in hidden:
            viewPrinter.fit(self.graphView.currentWidget(), 300, 150, expandH=True, expandV=True)

    def restoreSubviewsSize(self):
        graphHeight = self.model.graph_height_to_restore
        if graphHeight:
            splitterHeight = self.splitterView.height()
            sizes = [splitterHeight-graphHeight, graphHeight]
            self.splitterView.setSizes(sizes)

    # --- model --> view
    def refresh_reconciliation_button(self):
        if self.model.can_toggle_reconciliation_mode:
            self.reconciliationButton.setEnabled(True)
            self.reconciliationButton.setChecked(self.model.reconciliation_mode)
        else:
            self.reconciliationButton.setEnabled(False)
            self.reconciliationButton.setChecked(False)

    def show_bar_graph(self):
        self.graphView.setCurrentIndex(1)

    def show_line_graph(self):
        self.graphView.setCurrentIndex(0)

    def update_visibility(self):
        hidden = self.model.mainwindow.hidden_areas
        self.graphView.setHidden(PaneArea.BottomGraph in hidden)
class ParamModWgt(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.main_window = parent

        self.buildRequiredTagsGB()

        # Widgets        
        self.newParamBtn        = QPushButton("New")
        self.deleteParamBtn     = QPushButton("Delete")
        self.paramSaveAnnotBtn  = QPushButton("Save")
        buttonWidget             = QWidget(self)

        self.existingParamsGB     = QGroupBox("Existing parameters", self)

        self.paramListTblWdg      = QTableView()
        self.paramListModel     = ParameterListModel(parent=self)
        self.paramListTblWdg.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.paramListTblWdg.setSelectionMode(QAbstractItemView.SingleSelection)
        self.paramListTblWdg.setModel(self.paramListModel)

        self.paramListTblWdg.setColumnWidth(0, 150)
        self.paramListTblWdg.setColumnWidth(1, 350)

        self.relationWgt    = ParamRelationWgt(parent)
        self.newParamsGB    = QGroupBox("Parameter details", self)
        self.resultTypeCbo  = QComboBox(self)
        self.isExpProp      = QCheckBox("is an experimental property", self)

        self.resultTypeCbo.addItems(["point value", "function", "numerical trace"])
        
        self.singleValueParamWgt = ParamValueWgt(parent)
        self.functionParamWgt    = ParamFunctionWgt(parent)
        self.traceParamWgt       = ParamTraceWgt(parent)

        self.functionParamWgt.mainWgt = self

        self.paramModStack       = QStackedWidget(self)
        self.paramModStack.addWidget(self.singleValueParamWgt)
        self.paramModStack.addWidget(self.functionParamWgt)
        self.paramModStack.addWidget(self.traceParamWgt)

        # Signals
        selectionModel = self.paramListTblWdg.selectionModel()
        selectionModel.selectionChanged.connect(self.selectedParameterChanged)

        self.newParamBtn.clicked.connect(self.newParameter)
        self.deleteParamBtn.clicked.connect(self.deleteParameter)
        self.paramSaveAnnotBtn.clicked.connect(self.saveParameter)
        self.resultTypeCbo.currentIndexChanged.connect(self.paramModStack.setCurrentIndex)
        self.singleValueParamWgt.paramTypeSelected.connect(self.newParamTypeSelected)
        self.functionParamWgt.paramTypeSelected.connect(self.newParamTypeSelected)
        self.traceParamWgt.paramTypeSelected.connect(self.newParamTypeSelected)

        # Layout
        buttonLayout = QVBoxLayout(buttonWidget)
        buttonLayout.addWidget(self.paramSaveAnnotBtn)
        buttonLayout.addWidget(self.deleteParamBtn)
        buttonLayout.addWidget(self.newParamBtn)

        existGrid     = QHBoxLayout(self.existingParamsGB)
        existGrid.addWidget(buttonWidget)
        existGrid.addWidget(self.paramListTblWdg)
        
        newGrid     = QGridLayout(self.newParamsGB)
        newGrid.addWidget(QLabel("Result type"), 0, 0)
        newGrid.addWidget(self.resultTypeCbo, 0, 1)
        newGrid.addWidget(self.isExpProp, 0, 2)
        
        newGrid.addWidget(self.paramModStack, 1, 0, 1, 3)
        newGrid.addWidget(self.relationWgt, 1, 3)

        layout = QVBoxLayout(self)
        self.rootLayout = QSplitter(Qt.Vertical, self)
        self.rootLayout.setOrientation(Qt.Vertical)
        self.rootLayout.addWidget(self.existingParamsGB)
        self.rootLayout.addWidget(self.newParamsGB)
        self.rootLayout.addWidget(self.requireTagGB)
        layout.addWidget(self.rootLayout)

        # Initial behavior
        self.newParamBtn.setEnabled(True)
        self.deleteParamBtn.setEnabled(False)
        self.paramSaveAnnotBtn.setEnabled(False)
        self.additionMode = False
        self.newParamsGB.setEnabled(False)

    def setRootLayoutSizes(self, sizes):
        self.rootLayout.setSizes(sizes)


    def viewParameter(self, parameter):
        row = -1
        for row, param in enumerate(self.paramListModel.parameterList):
            if param.id == parameter.id:
                break
        assert(row > -1)
        self.paramListTblWdg.selectRow(row)

        

    @pyqtSlot(str)
    def newParamTypeSelected(self, paramName):
        self.requiredTagsListModel.clear()
        self.requiredTagsListModel.refresh()

        paramType  = getParameterTypeFromName(paramName)
        if paramType is None:
            raise ValueError("Parameter type with name '" + paramName + "' was not found.")

        for reqTag in paramType.requiredTags:
            self.requiredTagsListModel.addTag(reqTag.id, reqTag.name, reqTag.id, reqTag.name)

        self.requiredTagsListModel.refresh()


    def buildRequiredTagsGB(self):

        # Widgets            
        self.requireTagGB = QGroupBox("Required tag categories", self)

        self.requiredTagsListTblWdg      = RequiredTagsTableView() 
        self.requiredTagsListModel       = RequiredTagsListModel(parent=self)
        self.requiredTagsListTblWdg.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.requiredTagsListTblWdg.setSelectionMode(QAbstractItemView.SingleSelection)
        self.requiredTagsListTblWdg.setModel(self.requiredTagsListModel)
        self.requiredTagsListTblWdg.setColumnWidth(0, 200)
        self.requiredTagsListTblWdg.setColumnWidth(1, 200)

        # Layout
        requiredTagLayout = QGridLayout(self.requireTagGB)
        requiredTagLayout.addWidget(self.requiredTagsListTblWdg, 0, 0, 4, 1)


    def newParameter(self):
        self.resultTypeCbo.setCurrentIndex(0)
        self.paramModStack.currentWidget().newParameter()
        
        self.singleValueParamWgt.newParameter()
        self.functionParamWgt.newParameter()
        self.traceParamWgt.newParameter()       
        
        self.newParamsGB.setEnabled(True)
        self.paramListTblWdg.clearSelection()

        self.newParamBtn.setEnabled(False)
        self.deleteParamBtn.setEnabled(False)
        self.paramSaveAnnotBtn.setEnabled(True)

        self.isExpProp.setChecked(False)


    def saveParameter(self):

        relationship = self.relationWgt.getRelationship()
        
        # Get the ID of the modified parameter if we are modifying an existing
        # parameters        
        if len(self.paramListTblWdg.selectionModel().selectedRows()) != 0:
            selectedRow = self.paramListTblWdg.selectionModel().currentIndex().row()
            paramId = self.main_window.currentAnnotation.parameters[selectedRow].id
        else:
            paramId = None
        
        param = self.paramModStack.currentWidget().saveParameter(relationship, paramId)

        if not param is None:
            param.requiredTags             = self.requiredTagsListModel.getRequiredTags()
            param.isExperimentProperty     = self.isExpProp.isChecked()

            selectedRow = self.paramListTblWdg.selectionModel().currentIndex().row()
            # Even when there is no selection, selectedRow can take a zero value. This "if" 
            # controls for that.
            if len(self.paramListTblWdg.selectionModel().selectedRows()) == 0:
                selectedRow = -1

            if selectedRow >= 0:
                self.main_window.currentAnnotation.parameters[selectedRow] = param
            else:
                self.main_window.currentAnnotation.parameters.append(param)

            self.additionMode = False
            nbParams = len(self.main_window.currentAnnotation.parameters)
            self.main_window.saveAnnotation()

            if selectedRow < 0 :
                selectedRow = nbParams-1
            self.paramListTblWdg.selectRow(selectedRow)
            self.loadRow(selectedRow)     



    def deleteParameter(self):
        selectedRow = self.paramListTblWdg.selectionModel().currentIndex().row()
        del self.main_window.currentAnnotation.parameters[selectedRow]
        self.main_window.saveAnnotation()
        self.refreshModelingParameters()


    def refreshModelingParameters(self):
        selectedRow = self.paramListTblWdg.selectionModel().currentIndex().row()
        self.loadModelingParameter(selectedRow)


    def loadModelingParameter(self, row = None):
        """
         Call when a new annotation has been selected so that all the modeling parameters
         associated with this annotation are loaded in the parameter list. 
        """

        self.requiredTagsListModel.clear()
        self.requiredTagsListModel.refresh()

        if self.main_window.currentAnnotation is None:
            self.paramListModel.parameterList = []
        else:
            self.paramListModel.parameterList = self.main_window.currentAnnotation.parameters

            aRowIsSelected = not row is None
            if aRowIsSelected:
                if row < 0:
                    noRowToLoad = self.paramListTblWdg.model().rowCount()-row
                else:
                    noRowToLoad = row
            else:
                ## No rows are selected
                noRowToLoad = -1
            
            self.loadRow(noRowToLoad)
            self.newParamBtn.setEnabled(True)
            self.deleteParamBtn.setEnabled(aRowIsSelected)
            self.paramSaveAnnotBtn.setEnabled(aRowIsSelected)
            self.paramModStack.currentWidget().loadModelingParameter(row)
            self.relationWgt.loadModelingParameter(row)

            self.newParamsGB.setEnabled(aRowIsSelected)
        
        self.paramListModel.refresh()


    def loadRow(self, selectedRow = None):
        """
         Called when a row has been selected in the table listing all the modeling parameters.
         It update the interface with the values associated with this specific parameter.
        """
        
        def nlxCheck(id):
            if id in nlx2ks:
                return nlx2ks[id]
            return id
            
        def clear():
            self.requiredTagsListModel.clear()
            self.paramModStack.currentWidget().loadRow(None)
            self.relationWgt.clear()        
            self.paramListTblWdg.clearSelection()

        if selectedRow is None:
            selectedRow = self.paramListTblWdg.selectionModel().currentIndex().row()
        
        if self.main_window.currentAnnotation is None:
            clear()
            return
        
        if selectedRow < 0 or selectedRow >= len(self.main_window.currentAnnotation.parameters) :
            clear()
            return
            
        currentParameter = self.main_window.currentAnnotation.parameters[selectedRow]
    
        self.newParamBtn.setEnabled(True)
        self.deleteParamBtn.setEnabled(True)
        self.paramSaveAnnotBtn.setEnabled(True)

        if currentParameter.description.type == "pointValue":
            self.resultTypeCbo.setCurrentIndex(0)
            self.paramModStack.setCurrentIndex(0)
        elif currentParameter.description.type == "function": 
            self.resultTypeCbo.setCurrentIndex(1)
            self.paramModStack.setCurrentIndex(1)
        elif currentParameter.description.type == "numericalTrace": 
            self.resultTypeCbo.setCurrentIndex(2)
            self.paramModStack.setCurrentIndex(2)
        else:
            raise ValueError("Type of parameter description " + currentParameter.description.type + " is invalid.")

        self.paramModStack.currentWidget().loadRow(currentParameter)
        self.relationWgt.loadRow(currentParameter)
        self.isExpProp.setChecked(currentParameter.isExperimentProperty)

        ## UPDATING REQUIRED TAGS
        self.requiredTagsListModel.clear()       
        for tag in currentParameter.requiredTags:        
            self.requiredTagsListModel.addTag(tag.rootId, self.main_window.dicData[tag.rootId], tag.id, tag.name)
        
        ## Adding new required tags that may have been specified since the 
        ## creation of this parameter instance.
        parameterType = getParameterTypeFromID(currentParameter.typeId)
        reqTags = {reqTag.rootId:reqTag for reqTag in parameterType.requiredTags}
        for reqTagRootId, reqTag in reqTags.items():
            #print(nlxCheck(reqTagRootId), [nlxCheck(tag.rootId) for tag in currentParameter.requiredTags])
            if not nlxCheck(reqTagRootId) in [nlxCheck(tag.rootId) for tag in currentParameter.requiredTags]:
                self.requiredTagsListModel.addTag(reqTag.rootId, self.main_window.dicData[reqTag.rootId], reqTag.id, reqTag.name)
            
        self.requiredTagsListModel.refresh()

        self.newParamsGB.setEnabled(True)


    def selectedParameterChanged(self, selected, deselected):
        if len(selected.indexes()) == 0:
            return
        if self.additionMode:
            msgBox = QMessageBox(self)
            msgBox.setWindowTitle("Cancellation")
            msgBox.setText("Are you sure you want to cancel the addition of the new parameter being edited? If not, say no and then hit 'Save' to save this new parameter.")
            msgBox.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
            msgBox.setDefaultButton(QMessageBox.No)
            if msgBox.exec_() == QMessageBox.Yes:
                self.additionMode = False
                self.loadRow()
            else:
                #self.paramListTblWdg.selectRow(-1)
                self.paramListTblWdg.clearSelection()
        else:
            self.loadRow()
class VariantDataDialog(QDialog):
    def __init__(self, species=(), item=None, tax=True, last=0, index=QModelIndex(), count=0, length=0):
        """The constructor initializes the class NewVariantDialog."""
        super().__init__()
        self.item = item
        self.value = None
        self.speciesRegistry = species.keys()
        self.species = -1
        self.count = 0
        self.tax = tax
        self.index = index      # the last added index
        self.last = last
        self.count = count
        self.length = length


        self._OXYGEN_PATH_22 = os.path.join("resources", "icons", "oxygen", "22")
        self._LABEL_MIN_WIDTH = 240
        self._piece_unit = " St."
        self._currency_unit = " " + self.locale().currencySymbol(QLocale.CurrencyIsoCode)
        self._currency_unit_piece = self._currency_unit + "/" + self._piece_unit.strip()
        self._spinbox_step = 0.05


        self._COMBOBOX_ITEM_LIST = (QApplication.translate("VariantDataDialog", "Fence"),            # Zaun
                                    QApplication.translate("VariantDataDialog", "Tree shelter"))             # Wuchshülle

        # general things
        self.generalGroup = QGroupBox()

        self.variantInput = QComboBox()
        self.variantInput.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        self.variantInput.addItems(self._COMBOBOX_ITEM_LIST)
        self.variantLabel = QLabel()
        self.variantLabel.setMinimumWidth(self._LABEL_MIN_WIDTH)
        self.variantLabel.setBuddy(self.variantInput)
        self.variantHint = ToolTipLabel()

        self.descriptionInput = QLineEdit()
        self.descriptionLabel = QLabel()
        self.descriptionLabel.setBuddy(self.descriptionInput)
        self.descriptionHint = ToolTipLabel()

        # create the layout of the general group box
        generalLayout = QGridLayout(self.generalGroup)
        generalLayout.setVerticalSpacing(15)
        generalLayout.addWidget(self.variantLabel, 0, 0, Qt.AlignTop)
        generalLayout.addWidget(self.variantInput, 0, 1, Qt.AlignTop)
        generalLayout.addWidget(self.variantHint, 0, 2, Qt.AlignTop)
        generalLayout.addWidget(self.descriptionLabel, 1, 0, Qt.AlignTop)
        generalLayout.addWidget(self.descriptionInput, 1, 1, Qt.AlignTop)
        generalLayout.addWidget(self.descriptionHint, 1, 2, Qt.AlignTop)

        # plant specific input fields
        self.plantGroup = QGroupBox()

        self.speciesInput = QComboBox()
        self.speciesInput.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        self.speciesInput.addItems(library.TREESPECIES_DESCRIPTION)
        self.speciesLabel = QLabel()
        self.speciesLabel.setMinimumWidth(self._LABEL_MIN_WIDTH)
        self.speciesLabel.setBuddy(self.speciesInput)
        self.speciesHint = ToolTipLabel()
        self.speciesHint.hide()

        speciesSpacer = QSpacerItem(0, 30, QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.speciesWarningSymbol = QLabel(pixmap=QPixmap(os.path.join(self._OXYGEN_PATH_22, "dialog-warning.png")))
        self.speciesWarningSymbol.hide()
        self.speciesWarningText = QLabel(wordWrap=True)
        self.speciesWarningText.hide()
        warningLayout = QHBoxLayout()
        warningLayout.setContentsMargins(0, 0, 0, 0)
        warningLayout.addItem(speciesSpacer)
        warningLayout.addWidget(self.speciesWarningSymbol, alignment=Qt.AlignTop)
        warningLayout.addWidget(self.speciesWarningText, alignment=Qt.AlignTop)

        self.costInput = QDoubleSpinBox()
        self.costInput.setSuffix(self._currency_unit_piece)
        self.costInput.setSingleStep(self._spinbox_step)
        self.costLabel = QLabel()
        self.costLabel.setBuddy(self.costInput)
        self.costHint = ToolTipLabel()
        self.costHint.hide()
        self.costCalculator = QPushButton()

        self.preparationInput = QDoubleSpinBox()
        self.preparationInput.setSuffix(self._currency_unit_piece)
        self.preparationInput.setSingleStep(self._spinbox_step)
        self.preparationLabel = QLabel()
        self.preparationLabel.setBuddy(self.preparationInput)
        self.preparationHint = ToolTipLabel()
        self.preparationHint.hide()
        self.preparationCalculator = QPushButton()

        self.plantingInput = QDoubleSpinBox()
        self.plantingInput.setSuffix(self._currency_unit_piece)
        self.plantingInput.setSingleStep(self._spinbox_step)
        self.plantingLabel = QLabel()
        self.plantingLabel.setBuddy(self.plantingInput)
        self.plantingHint = ToolTipLabel()
        self.plantingHint.hide()
        self.plantingCalculator = QPushButton()

        self.tendingInput = QDoubleSpinBox()
        self.tendingInput.setSuffix(self._currency_unit_piece)
        self.tendingInput.setSingleStep(self._spinbox_step)
        self.tendingLabel = QLabel()
        self.tendingLabel.setBuddy(self.tendingInput)
        self.tendingHint = ToolTipLabel()
        self.tendingHint.hide()
        self.tendingCalculator = QPushButton()

        self.mortalityInput = QSpinBox()
        self.mortalityInput.setSuffix(" %")
        self.mortalityInput.setMaximum(100)
        self.mortalityInput.setValue(0)
        self.mortalityInput.setDisabled(True)
        self.mortalityLabel = QLabel()
        self.mortalityLabel.setBuddy(self.mortalityInput)
        self.mortalityHint = ToolTipLabel()
        self.mortalityHint.hide()

        # create the layout of the plant group box
        plantLayout = QGridLayout(self.plantGroup)
        plantLayout.addWidget(self.speciesLabel, 0, 0)
        plantLayout.addWidget(self.speciesInput, 0, 1)
        plantLayout.addWidget(self.speciesHint, 0, 2)
        plantLayout.addLayout(warningLayout, 1, 1)
        plantLayout.addWidget(self.costLabel, 2, 0)
        plantLayout.addWidget(self.costInput, 2, 1)
        plantLayout.addWidget(self.costHint, 2, 2)
        plantLayout.addWidget(self.costCalculator, 2, 3)
        plantLayout.addWidget(self.preparationLabel, 3, 0)
        plantLayout.addWidget(self.preparationInput, 3, 1)
        plantLayout.addWidget(self.preparationHint, 3, 2)
        plantLayout.addWidget(self.preparationCalculator, 3, 3)
        plantLayout.addWidget(self.plantingLabel, 4, 0)
        plantLayout.addWidget(self.plantingInput, 4, 1)
        plantLayout.addWidget(self.plantingHint, 4, 2)
        plantLayout.addWidget(self.plantingCalculator, 4, 3)
        plantLayout.addWidget(self.tendingLabel, 5, 0)
        plantLayout.addWidget(self.tendingInput, 5, 1)
        plantLayout.addWidget(self.tendingHint, 5, 2)
        plantLayout.addWidget(self.tendingCalculator, 5, 3)
        plantLayout.addWidget(self.mortalityLabel, 6, 0)
        plantLayout.addWidget(self.mortalityInput, 6, 1)
        plantLayout.addWidget(self.mortalityHint, 6, 2)

        # stacked widget for protection group
        self.fenceWidget = FenceInputWidget(self.tax)
        self.fenceWidget.length = self.length
        self.tubeWidget = TubeInputWidget(self.tax)

        self.protectionGroup = QStackedWidget()
        self.protectionGroup.addWidget(self.fenceWidget)
        self.protectionGroup.addWidget(self.tubeWidget)

        # sales tax hint
        taxLabel = QLabel("*) " + QApplication.translate("VariantDataDialog",                      # Bitte beachten Sie, dass Sie den Variantentyp später nicht mehr ändern können.
                "Keep in mind, that all values must contain uniformly "
                "the sales tax or not."),
                wordWrap=True)

        # create an ok button and abort button within a button box
        lineFrame = QFrame(frameShadow=QFrame.Sunken, frameShape=QFrame.VLine)
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel|QDialogButtonBox.Help,
                orientation=Qt.Vertical)

        # create main layout
        dataLayout = QVBoxLayout()
        dataLayout.addWidget(self.generalGroup)
        dataLayout.addWidget(self.plantGroup)
        dataLayout.addWidget(self.protectionGroup)
        dataLayout.addWidget(taxLabel)
        dataLayout.addStretch()

        layout = QHBoxLayout(self)
        layout.addLayout(dataLayout)
        layout.addWidget(lineFrame)
        layout.addWidget(self.buttonBox)

        # connect actions
        self.variantInput.currentIndexChanged.connect(self.variantChanged)

        self.speciesInput.currentIndexChanged.connect(self.checkSpecies)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.helpRequested.connect(self.help)

        self.costCalculator.clicked.connect(self.costCalculation)
        self.preparationCalculator.clicked.connect(self.preparationCalculation)
        self.plantingCalculator.clicked.connect(self.plantingCalculation)
        self.tendingCalculator.clicked.connect(self.tendingCalculation)

        self.tubeWidget.countChanged.connect(self.updateCount)
        self.fenceWidget.lengthChanged.connect(self.updateLength)

        # update input fields
        if self.item:
            plant = self.item[TreeModel.PlantRole]
            protection = self.item[TreeModel.ProtectionRole]

            self.species = plant.species

            # update input fields
            self.variantInput.setCurrentIndex(protection.TYPE)
            self.variantInput.setDisabled(True)
            self.descriptionInput.setText(self.item[TreeModel.NameRole])
            self.speciesInput.setCurrentIndex(plant.species)
            self.costInput.setValue(plant.cost)
            self.preparationInput.setValue(plant.preparation)
            self.plantingInput.setValue(plant.planting)
            self.tendingInput.setValue(plant.tending)
            self.mortalityInput.setValue(plant.mortality * 100)

            # update the protection group
            self.protectionGroup.currentWidget().setValues(protection)
        else:
            self.variantInput.setCurrentIndex(self.last)
            if self.index.isValid():
                self.speciesInput.setCurrentIndex(self.index.data(TreeModel.SpeciesRole))

        # check the species and show
        # a warning, if necessary
        self.checkSpecies()

        # translate the graphical user interface
        self.retranslateUi()

    def updateCount(self, count):
        # TODO
        self.count = count

    def updateLength(self, length):
        # TODO
        self.length = length

    def retranslateUi(self):
        # dialog title
        self.setWindowTitle(QApplication.translate("VariantDataDialog", "Edit protection"))                         # Schutz bearbeiten

        # variant selection
        self.generalGroup.setTitle(QApplication.translate("VariantDataDialog", "Selection of protection"))          # Auswahl des Schutzes
        self.variantLabel.setText(QApplication.translate("VariantDataDialog", "Protection type") + ":")             # Schutztyp
        self.descriptionLabel.setText(QApplication.translate("VariantDataDialog", "Protection description") + ":")     # Schutzbeschreibung
        self.variantHint.setToolTip(QApplication.translate("VariantDataDialog",                                     # Bitte beachten Sie, dass Sie den Variantentyp später nicht mehr ändern können.
                "Keep in mind, that you can't change the variant type "
                "at a later time."))
        self.descriptionHint.setToolTip(QApplication.translate("VariantDataDialog",                                 # Geben Sie eine Beschreibung der Variante ein, um sie später identifizieren zu können.
                "Please describe the variant. The description helps you "
                "identify it."))

        # plant input
        self.plantGroup.setTitle(QApplication.translate("VariantDataDialog", "Cost of plants and planting"))        # Kosten Pflanze und Pflanzung
        self.speciesLabel.setText(QApplication.translate("VariantDataDialog", "Tree species") + ":")                # Baumart
        self.speciesHint.setToolTip("Text")
        self.speciesWarningText.setText(QApplication.translate("VariantDataDialog",
                "A fence with the selected species exists already!"))                                               # Es existiert bereits ein Zaun mit der ausgewählten Baumart!
        self.costLabel.setText(QApplication.translate("VariantDataDialog", "Unit cost") + "*:")                     # Stückkosten
        self.costHint.setToolTip("Text")
        self.costCalculator.setText(QApplication.translate("VariantDataDialog", "Calculation help"))                # Umrechnungshilfe
        self.preparationLabel.setText(QApplication.translate("VariantDataDialog", "Cost of preparation") + "*:")    # Kulturvorbereitung
        self.preparationHint.setToolTip("Text")
        self.preparationCalculator.setText(QApplication.translate("VariantDataDialog", "Calculation help"))         # Umrechnungshilfe
        self.plantingLabel.setText(QApplication.translate("VariantDataDialog", "Cost of planting") + "*:")          # Pflanzungskosten
        self.plantingHint.setToolTip("Text")
        self.plantingCalculator.setText(QApplication.translate("VariantDataDialog", "Calculation help"))            # Umrechnungshilfe
        self.tendingLabel.setText(QApplication.translate("VariantDataDialog", "Cost of tending (5 years)") + "*:")  # Kultursicherung
        self.tendingHint.setToolTip("Text")
        self.tendingCalculator.setText(QApplication.translate("VariantDataDialog", "Calculation help"))             # Umrechnungshilfe
        self.mortalityLabel.setText(QApplication.translate("MainWindow", "Decreased &mortality over fence") + ":")  # &Mortalitätsrate
        self.mortalityHint.setToolTip("Text")

    def help(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))

    def variantChanged(self, index):
        # check for species
        self.checkSpecies()

        # update the visible status of the mortality input
        if index == Tube.TYPE:
            self.mortalityInput.setValue(10)
            self.mortalityInput.setEnabled(True)
        else:
            self.mortalityInput.setValue(0)
            self.mortalityInput.setDisabled(True)

        # set up the protection group
        self.protectionGroup.setCurrentIndex(index)

    def accept(self):
        # check name input field
        if not self.descriptionInput.text():
            warning = QMessageBox(self)
            warning.setWindowModality(Qt.WindowModal)  # check for mac only
            warning.setIcon(QMessageBox.Warning)
            warning.setStandardButtons(QMessageBox.Ok)
            warning.setWindowTitle(QApplication.translate("VariantDataDialog", "Wuchshüllenrechner"))
            warning.setText("<b>" + QApplication.translate("VariantDataDialog",
                    "The variant description is missing!") + "</b>")
            warning.setInformativeText(QApplication.translate("VariantDataDialog",
                    "Please describe your new variant."))

            warning.exec()
        else:
            # return the input values
            plant = Plant()
            plant.species = self.speciesInput.currentIndex()
            plant.cost = self.costInput.value()
            plant.preparation = self.preparationInput.value()
            plant.planting = self.plantingInput.value()
            plant.tending = self.tendingInput.value()
            plant.mortality = self.mortalityInput.value() / 100 if self.mortalityInput.value() > 0 else 0

            protection = self.protectionGroup.currentWidget().values()

            if not self.item:
                if protection.TYPE == Fence.TYPE:
                    color = QColor(255, 0, 0).name()
                else:
                    color = QColor(random.randint(0, 256), random.randint(0, 256),
                            random.randint(0, 256)).name()
            else:
                color = self.item[TreeModel.ColorRole]

            self.value = {
                TreeModel.NameRole : self.descriptionInput.text(),
                TreeModel.ColorRole : color,
                TreeModel.StatusRole : True,
                TreeModel.PlantRole : plant,
                TreeModel.ProtectionRole : protection
            }

            super().accept()

    def checkSpecies(self):
        species = self.speciesInput.currentIndex()

        # only for fence variants
        if self.variantInput.currentIndex() == Fence.TYPE:
            if not species == self.species and species in self.speciesRegistry:
                # first disable the OK button
                self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
                self.speciesWarningSymbol.show()
                self.speciesWarningText.show()
            else:
                self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
                self.speciesWarningSymbol.hide()
                self.speciesWarningText.hide()
        else:
            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
            self.speciesWarningSymbol.hide()
            self.speciesWarningText.hide()

    def costCalculation(self):
        value = self.unitCostCalculator()
        if value > 0:
            self.costInput.setValue(value)

    def preparationCalculation(self):
        value = self.unitCostCalculator()
        if value > 0:
            self.preparationInput.setValue(value)

    def plantingCalculation(self):
        value = self.unitCostCalculator()
        if value > 0:
            self.plantingInput.setValue(value)

    def tendingCalculation(self):
        value = self.unitCostCalculator()
        if value > 0:
            self.tendingInput.setValue(value)

    def unitCostCalculator(self):
        dialog = UnitCostDialog(self.count)
        dialog.exec()

        # TODO
        self.count = dialog.count
        self.tubeWidget.count = self.count

        return dialog.value
Пример #46
0
class PreferencesDialog(QDialog):
    """Creates a dialog that shows the user all of the user configurable options.

    A list on the left shows all of the available pages, with
    the page's contents shown on the right.
    """

    def __init__(self, parent=None):
        """Initialize the preferences dialog with a list box and a content layout."""
        super(PreferencesDialog, self).__init__(parent)
        self.setWindowTitle('Preferences')

        settings_icon = utilities.resource_filename('mosaic.images', 'md_settings.png')
        self.setWindowIcon(QIcon(settings_icon))
        self.resize(600, 450)

        self.contents = QListWidget()
        self.contents.setFixedWidth(175)
        self.pages = QStackedWidget()
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok)

        self.dialog_media_library = MediaLibrary()
        self.dialog_playback = Playback()
        self.dialog_view_options = ViewOptions()
        self.pages.addWidget(self.dialog_media_library)
        self.pages.addWidget(self.dialog_playback)
        self.pages.addWidget(self.dialog_view_options)
        self.list_items()

        stack_layout = QVBoxLayout()
        stack_layout.addWidget(self.pages)
        stack_layout.addWidget(self.button_box)

        layout = QHBoxLayout()
        layout.addWidget(self.contents)
        layout.addLayout(stack_layout)

        self.setLayout(layout)

        self.contents.currentItemChanged.connect(self.change_page)
        self.button_box.accepted.connect(self.accept)

    def list_items(self):
        """List all of the pages available to the user."""
        media_library_options = QListWidgetItem(self.contents)
        media_library_options.setText('Media Library')
        media_library_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.contents.setCurrentRow(0)

        playback_options = QListWidgetItem(self.contents)
        playback_options.setText('Playback')
        playback_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

        view_options = QListWidgetItem(self.contents)
        view_options.setText('View Options')
        view_options.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

    def change_page(self, current, previous):
        """Change the page according to the clicked list item."""
        if not current:
            current = previous

        self.pages.setCurrentIndex(self.contents.row(current))
Пример #47
0
 def setCurrentIndex(self, index):
     self.fader_widget = ui_tools.FaderWidget(self.currentWidget(),
         self.widget(index))
     QStackedWidget.setCurrentIndex(self, index)
Пример #48
0
class FlowDialog(QWidget):
    """
    Class for controlling the order of screens in the experiment.
    """

    def __init__(self, parent=None):
        super(FlowDialog, self).__init__(parent)
        self._n_steps = 1  # number of performed steps

        self.pages_widget = QStackedWidget()

        # create widgets
        self.experiment_setup = ExperimentSetup()
        self.instructions = InstructionsScreen("./instructions/he-informed-consent.txt")
        self.new_user_form = NewUserForm()
        self.data_widget = DataWidget()

        # add widgets to pages_widget
        self.pages_widget.addWidget(self.experiment_setup)
        self.pages_widget.addWidget(self.instructions)
        self.pages_widget.addWidget(self.new_user_form)
        self.pages_widget.addWidget(self.data_widget)

        # next button
        self.next_button = QPushButton("&Next")
        self.next_button_layout = QHBoxLayout()
        self.next_button_layout.addStretch(1)
        self.next_button_layout.addWidget(self.next_button)
        self.next_button.pressed.connect(self.nextPressed)

        main_layout = QGridLayout()

        # set screen shoulders
        main_layout.setRowMinimumHeight(0, 80)
        main_layout.setRowMinimumHeight(3, 80)
        main_layout.setColumnMinimumWidth(0, 80)
        main_layout.setColumnMinimumWidth(2, 80)
        main_layout.addWidget(self.pages_widget, 1, 1)
        main_layout.addLayout(self.next_button_layout, 2, 1)
        self.setLayout(main_layout)
        self.pages_widget.setCurrentIndex(0)

    def nextPressed(self):
        """
        control the order and number of repetitions of the experiment
        """
        self.data_widget.count_down_timer.restart_timer()  # restart timer

        # if on setup screen
        if self.pages_widget.currentIndex() == 0:
            # get condition index number
            condition_index = self.experiment_setup.conditions_combo.currentIndex()
            # DEBUGGING:
            debug_condition = config.CONDITIONS['a'][condition_index]
            print(debug_condition)

            self.raise_index()

        # welcome screen
        elif self.pages_widget.currentIndex() == 1:
            self.raise_index()

        # if on new_user screen
        elif self.pages_widget.currentIndex() == 2:
            self.new_user_form.save_results()
            self.raise_index()

        # if on data screen
        elif self.pages_widget.currentIndex() == 3:
            if self._n_steps < config.NUM_STEPS:
                self.data_widget.add_log_row()
                self._n_steps += 1
                print("Step number {}".format(self._n_steps))  # DEBUGGING
            else:
                self.raise_index()

        elif self.pages_widget.currentIndex() == 4:
            print("That's it")  # DEBUGGING

        else:
            # If reached wrong index
            raise RuntimeError("No such index")

    def raise_index(self):
        current = self.pages_widget.currentIndex()
        self.pages_widget.setCurrentIndex(current + 1)
Пример #49
0
class _ToolsDock(QWidget):

    __WIDGETS = {}
    __created = False
    __index = 0

    # Signals
    executeFile = pyqtSignal()
    executeProject = pyqtSignal()
    executeSelection = pyqtSignal()
    stopApplication = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        # Register signals connections
        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.__buttons = []
        self.__action_number = 1
        self.__buttons_visibility = {}
        self.__current_widget = None
        self.__last_index = -1

        self._stack_widgets = QStackedWidget()
        layout.addWidget(self._stack_widgets)

        # Buttons Widget
        self.buttons_widget = QWidget()
        self.buttons_widget.setObjectName("tools_dock")
        self.buttons_widget.setFixedHeight(26)
        self.buttons_widget.setLayout(QHBoxLayout())
        self.buttons_widget.layout().setContentsMargins(2, 2, 5, 2)
        self.buttons_widget.layout().setSpacing(10)

        IDE.register_service("tools_dock", self)
        _ToolsDock.__created = True

    @classmethod
    def register_widget(cls, display_name, obj):
        """Register a widget providing the service name and the instance"""

        cls.__WIDGETS[cls.__index] = (obj, display_name)
        cls.__index += 1

    def install(self):
        self._load_ui()
        ninjaide = IDE.get_service("ide")
        ninjaide.place_me_on("tools_dock", self, "central")
        ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide)
        ninjaide.goingDown.connect(self._save_settings)
        ninja_settings = IDE.ninja_settings()
        index = int(ninja_settings.value("tools_dock/widgetVisible", -1))
        if index == -1:
            self.hide()
        else:
            self._show(index)

    def _load_ui(self):
        ninjaide = IDE.get_service("ide")

        shortcut_number = 1

        for index, (obj, name) in _ToolsDock.__WIDGETS.items():
            button = ToolButton(name, index + 1)
            button.setCheckable(True)
            button.clicked.connect(self.on_button_triggered)
            self.__buttons.append(button)
            self.buttons_widget.layout().addWidget(button)
            self.add_widget(name, obj)
            self.__buttons_visibility[button] = True
            # Shortcut action
            ksequence = self._get_shortcut(shortcut_number)
            short = QShortcut(ksequence, ninjaide)
            button.setToolTip(
                ui_tools.tooltip_with_shortcut(button._text, ksequence))
            short.activated.connect(self._shortcut_triggered)
            shortcut_number += 1

        self.buttons_widget.layout().addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding))

        # Python Selector
        btn_selector = ui_tools.FancyButton("Loading...")
        btn_selector.setIcon(ui_tools.get_icon("python"))
        btn_selector.setCheckable(True)
        btn_selector.setEnabled(False)
        self.buttons_widget.layout().addWidget(btn_selector)

        # QML Interface
        self._python_selector = python_selector.PythonSelector(btn_selector)

        interpreter_srv = IDE.get_service("interpreter")
        interpreter_srv.foundInterpreters.connect(
            self._python_selector.add_model)

        btn_selector.toggled[bool].connect(
            lambda v: self._python_selector.setVisible(v))

        # Popup for show/hide tools widget
        button_toggle_widgets = ToggleButton()
        self.buttons_widget.layout().addWidget(button_toggle_widgets)
        button_toggle_widgets.clicked.connect(self._show_menu)

    def _get_shortcut(self, short_number: int):
        """Return shortcut as ALT + number"""

        if short_number < 1 or short_number > 9:
            return QKeySequence()
        modifier = Qt.ALT if not settings.IS_MAC_OS else Qt.CTRL
        return QKeySequence(modifier + (Qt.Key_0 + short_number))

    def _shortcut_triggered(self):
        short = self.sender()
        widget_index = int(short.key().toString()[-1]) - 1
        widget = self.widget(widget_index)
        if widget.isVisible():
            self._hide()
        else:
            self._show(widget_index)

    def _show_menu(self):
        menu = QMenu()
        for n, (obj, display_name) in _ToolsDock.__WIDGETS.items():
            action = menu.addAction(display_name)
            action.setCheckable(True)
            action.setData(n)

            button = self.__buttons[n]
            visible = self.__buttons_visibility.get(button)
            action.setChecked(visible)

        result = menu.exec_(QCursor.pos())

        if not result:
            return
        index = result.data()
        btn = self.__buttons[index]
        visible = self.__buttons_visibility.get(btn, False)
        self.__buttons_visibility[btn] = not visible
        if visible:
            btn.hide()
        else:
            btn.show()

    def get_widget_index_by_instance(self, instance):
        index = -1
        for i, (obj, _) in self.__WIDGETS.items():
            if instance == obj:
                index = i
                break
        return index

    def execute_file(self):
        run_widget = IDE.get_service("run_widget")
        index = self.get_widget_index_by_instance(run_widget)
        self._show(index)
        self.executeFile.emit()

    def execute_project(self):
        run_widget = IDE.get_service("run_widget")
        index = self.get_widget_index_by_instance(run_widget)
        self._show(index)
        self.executeProject.emit()

    def execute_selection(self):
        run_widget = IDE.get_service("run_widget")
        index = self.get_widget_index_by_instance(run_widget)
        self._show(index)
        self.executeSelection.emit()

    def kill_application(self):
        self.stopApplication.emit()

    def add_widget(self, display_name, obj):
        self._stack_widgets.addWidget(obj)
        func = getattr(obj, "install_widget", None)
        if isinstance(func, collections.Callable):
            func()

    def on_button_triggered(self):
        # Get button index
        button = self.sender()
        index = self.__buttons.index(button)
        if index == self.current_index() and self._is_current_visible():
            self._hide()
        else:
            self._show(index)

    def widget(self, index):
        return self.__WIDGETS[index][0]

    def _hide(self):
        self.__current_widget.setVisible(False)
        index = self.current_index()
        self.__buttons[index].setChecked(False)
        self.widget(index).setVisible(False)
        self.hide()

    def hide_widget(self, obj):
        index = self.get_widget_index_by_instance(obj)
        self.set_current_index(index)
        self._hide()

    def _show(self, index):
        widget = self.widget(index)
        self.__current_widget = widget
        widget.setVisible(True)
        widget.setFocus()
        self.set_current_index(index)
        self.show()

    def set_current_index(self, index):
        if self.__last_index != -1:
            self.__buttons[self.__last_index].setChecked(False)
        self.__buttons[index].setChecked(True)
        if index != -1:
            self._stack_widgets.setCurrentIndex(index)
            widget = self.widget(index)
            widget.setVisible(True)
        self.__last_index = index

    def current_index(self):
        return self._stack_widgets.currentIndex()

    def _is_current_visible(self):
        return self.__current_widget and self.__current_widget.isVisible()

    def _save_settings(self):
        ninja_settings = IDE.ninja_settings()
        visible_widget = self.current_index()
        if not self.isVisible():
            visible_widget = -1
        ninja_settings.setValue("tools_dock/widgetVisible", visible_widget)
Пример #50
0
class GstMediaSettings(SettingsSection):

    Name = 'Media Settings'

    def __init__(self, size, cue=None, parent=None):
        super().__init__(size, cue=cue, parent=parent)
        self._pipe = ''
        self._conf = {}
        self._check = False

        self.glayout = QGridLayout(self)

        self.listWidget = QListWidget(self)
        self.glayout.addWidget(self.listWidget, 0, 0)

        self.pipeButton = QPushButton('Change Pipe', self)
        self.glayout.addWidget(self.pipeButton, 1, 0)

        self.elements = QStackedWidget(self)
        self.glayout.addWidget(self.elements, 0, 1, 2, 1)

        self.glayout.setColumnStretch(0, 2)
        self.glayout.setColumnStretch(1, 5)

        self.listWidget.currentItemChanged.connect(self.__change_page)
        self.pipeButton.clicked.connect(self.__edit_pipe)

    def set_configuration(self, conf):
        # Get the media section of the cue configuration
        if conf is not None:
            conf = conf.get('media', {})

            # Activate the layout, so we can get the right widgets size
            self.glayout.activate()

            # Create a local copy of the configuration
            self._conf = deepcopy(conf)

            # Create the widgets
            sections = sections_by_element_name()
            for element in conf.get('pipe', '').split('!'):
                widget = sections.get(element)

                if widget is not None:
                    widget = widget(self.elements.size(), element, self)
                    widget.set_configuration(self._conf['elements'])
                    self.elements.addWidget(widget)

                    item = QListWidgetItem(widget.NAME)
                    self.listWidget.addItem(item)

            self.listWidget.setCurrentRow(0)

    def get_configuration(self):
        conf = {'elements': {}}

        for el in self.elements.children():
            if isinstance(el, SettingsSection):
                conf['elements'].update(el.get_configuration())

        # If in check mode the pipeline is not returned
        if not self._check:
            conf['pipe'] = self._conf['pipe']

        return {'media': conf}

    def enable_check(self, enable):
        self._check = enable
        for element in self.elements.children():
            if isinstance(element, SettingsSection):
                element.enable_check(enable)

    def __change_page(self, current, previous):
        if not current:
            current = previous

        self.elements.setCurrentIndex(self.listWidget.row(current))

    def __edit_pipe(self):
        # Backup the settings
        self._conf.update(self.get_configuration()['media'])

        # Show the dialog
        dialog = GstPipeEdit(self._conf.get('pipe', ''), parent=self)

        if dialog.exec_() == dialog.Accepted:
            # Reset the view
            for _ in range(self.elements.count()):
                self.elements.removeWidget(self.elements.widget(0))
            self.listWidget.clear()

            # Reload with the new pipeline
            self._conf['pipe'] = dialog.get_pipe()

            self.set_configuration({'media': self._conf})
            self.enable_check(self._check)
Пример #51
0
class SettingsWidget(QWidget):

    settings_changed = pyqtSignal()

    def __init__(self, parent: QWidget):
        super(SettingsWidget, self).__init__(parent, Qt.Window)
        # config parser
        self._cfg = configparser.ConfigParser()
        # layouts
        self._layout_main = QVBoxLayout()
        self._layout_stacks = QHBoxLayout()
        self._layout_okcancel = QHBoxLayout()
        # sections list
        self._sections_list = QListWidget(self)
        self._sections_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self._sections_list.setSelectionBehavior(QAbstractItemView.SelectItems)
        self._sections_list.setIconSize(QSize(32, 32))
        self._sections_list.setViewMode(QListView.IconMode)
        self._sections_list.setMaximumWidth(80)
        self._sections_list.setGridSize(QSize(64, 64))
        self._sections_list.setFlow(QListView.TopToBottom)
        self._sections_list.setMovement(QListView.Static)  # items cannot be moved by user
        # network item
        lwi = QListWidgetItem()
        lwi.setText(self.tr("Network"))
        lwi.setTextAlignment(Qt.AlignCenter)
        lwi.setIcon(QIcon(":/i/settings_network_32.png"))
        lwi.setData(Qt.UserRole, QVariant(0))
        self._sections_list.addItem(lwi)
        lwi.setSelected(True)
        # misc item
        lwi = QListWidgetItem()
        lwi.setText(self.tr("Other"))
        lwi.setTextAlignment(Qt.AlignCenter)
        lwi.setIcon(QIcon(":/i/settings_32.png"))
        lwi.setData(Qt.UserRole, QVariant(1))
        self._sections_list.addItem(lwi)
        # connections
        self._sections_list.currentItemChanged.connect(self.on_section_current_item_changed)
        self._layout_stacks.addWidget(self._sections_list)
        # stacked widget
        self._stack = QStackedWidget(self)
        self._w_net = Settings_Net(self._stack)
        self._w_misc = Settings_Misc(self._stack)
        self._stack.addWidget(self._w_net)
        self._stack.addWidget(self._w_misc)
        self._stack.setCurrentIndex(0)
        self._layout_stacks.addWidget(self._stack)
        # ok cancel buttons
        self._btn_ok = QPushButton(self)
        self._btn_ok.setText(self.tr("Save"))
        self._btn_ok.setIcon(QIcon(":/i/save.png"))
        self._btn_cancel = QPushButton(self)
        self._btn_cancel.setText(self.tr("Cancel"))
        self._btn_cancel.setIcon(QIcon(":/i/cancel.png"))
        self._layout_okcancel.addStretch()
        self._layout_okcancel.addWidget(self._btn_ok)
        self._layout_okcancel.addWidget(self._btn_cancel)
        self._btn_ok.clicked.connect(self.on_ok)
        self._btn_cancel.clicked.connect(self.on_cancel)
        # final
        self._layout_main.addLayout(self._layout_stacks)
        self._layout_main.addLayout(self._layout_okcancel)
        self.setLayout(self._layout_main)
        self.setWindowTitle(self.tr("Settings"))
        self.setWindowIcon(QIcon(":/i/settings_32.png"))
        #
        self.load_settings()

    def load_settings(self):
        self._cfg.read("config/net.ini", encoding="utf-8")
        # init config of all child widgets
        self._w_net.load_from_config(self._cfg)
        self._w_misc.load_from_config(self._cfg)

    def save_settings(self):
        # read config from all child widgets
        self._w_net.save_to_config(self._cfg)
        self._w_misc.save_to_config(self._cfg)
        # save to file
        try:
            with open("config/net.ini", "wt", encoding="utf-8") as fp:
                self._cfg.write(fp)
                fp.write("# proxy Tor example (local Tor browser):\n")
                fp.write("# proxy = socks5://127.0.0.1:9050\n")
                fp.write("# proxy I2P example:\n")
                fp.write("# proxy = http://127.0.0.1:4444\n")
        except IOError as e:
            logger.error(str(e))
        self.settings_changed.emit()

    @pyqtSlot()
    def on_ok(self):
        self.save_settings()
        self.hide()

    def on_cancel(self):
        self.hide()

    @pyqtSlot(QListWidgetItem, QListWidgetItem)
    def on_section_current_item_changed(self, cur: QListWidgetItem, prev: QListWidgetItem):
        data = int(cur.data(Qt.UserRole))
        self._stack.setCurrentIndex(data)
Пример #52
0
class XTabWidget(QFrame):

    addClicked = pyqtSignal()
    currentChanged = pyqtSignal(int)
    tabCloseRequested = pyqtSignal(int)

    def __init__(self, QWidget_parent=None):
        super(XTabWidget, self).__init__(QWidget_parent)
        # setup self frame
        self.setFrameShadow(QFrame.Raised)
        # self.setFrameShape(QFrame.StyledPanel)
        self.setFrameShape(QFrame.NoFrame)
        # layouts
        self._layout = QVBoxLayout()
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(2)
        self._layout_top = QHBoxLayout()
        self._layout_top.setContentsMargins(0, 0, 0, 0)
        # stacked widget
        self._stack = QStackedWidget(self)
        # tab bar
        self._tabbar = QTabBar(self)
        self._tabbar.setTabsClosable(True)
        self._tabbar.setMovable(False)
        self._tabbar.setExpanding(False)
        self._tabbar.setShape(QTabBar.RoundedNorth)
        self._tabbar.currentChanged.connect(self.on_tab_current_changed)
        self._tabbar.tabCloseRequested.connect(self.on_tab_close_requested)
        # button "add"
        self._btn_add = QPushButton('+', self)
        self._btn_add.setMaximumSize(QSize(22, 22))
        self._btn_add.clicked.connect(self.on_btn_add_clicked)
        # complete layout
        self._layout_top.addWidget(self._btn_add, 0, Qt.AlignVCenter)
        self._layout_top.addWidget(self._tabbar, 1, Qt.AlignVCenter)
        self._layout.addLayout(self._layout_top)
        self._layout.addWidget(self._stack)
        self.setLayout(self._layout)

    def addTab(self, widget: QWidget, title: str, closeable: bool = True) -> int:
        # add tab to tabbar
        tab_index = self._tabbar.addTab(title)
        if not closeable:
            self._tabbar.setTabButton(tab_index, QTabBar.RightSide, None)
            self._tabbar.setTabButton(tab_index, QTabBar.LeftSide, None)  # it MAY be on the left too!!
        # add widget into stackedwidget
        self._stack.addWidget(widget)
        return tab_index

    def removeTab(self, index: int):
        # remove from tab bar
        self._tabbar.removeTab(index)
        # remove from stacked widget
        widget = self._stack.widget(index)
        if widget is not None:
            # Removes widget from the QStackedWidget. i.e., widget
            # is not deleted but simply removed from the stacked layout,
            # causing it to be hidden.
            self._stack.removeWidget(widget)
            # and now we probably want to delete it to avoid memory leak
            widget.close()
            widget.deleteLater()

    def tabBar(self) -> QTabBar:
        return self._tabbar

    def enableButtonAdd(self, enableState: bool = True):
        self._btn_add.setEnabled(enableState)

    def setCurrentIndex(self, index: int):
        self._stack.setCurrentIndex(index)
        self._tabbar.setCurrentIndex(index)

    def count(self) -> int:
        return self._tabbar.count()

    def tabWidget(self, index: int):
        """
        Return page widget, inserted at index index
        :param index:
        :return: QWidget inserted at specified index, or None
        """
        widget = self._stack.widget(index)
        return widget

    @pyqtSlot()
    def on_btn_add_clicked(self):
        self.addClicked.emit()

    @pyqtSlot(int)
    def on_tab_current_changed(self, idx: int):
        self._stack.setCurrentIndex(idx)
        self.currentChanged.emit(idx)

    @pyqtSlot(int)
    def on_tab_close_requested(self, idx: int):
        self.tabCloseRequested.emit(idx)
Пример #53
0
class AddDialog(QDialog):
    worker = None
    selected_show = None
    results = []

    def __init__(self, parent, worker, current_status, default=None):
        QDialog.__init__(self, parent)
        self.resize(950, 700)
        self.setWindowTitle('Search/Add from Remote')
        self.worker = worker
        self.current_status = current_status
        self.default = default
        if default:
            self.setWindowTitle('Search/Add from Remote for new show: %s' % default)
        
        # Get available search methods and default to keyword search if not reported by the API
        search_methods = self.worker.engine.mediainfo.get('search_methods', [utils.SEARCH_METHOD_KW])

        layout = QVBoxLayout()

        # Create top layout
        top_layout = QHBoxLayout()

        if utils.SEARCH_METHOD_KW in search_methods:
            self.search_rad = QRadioButton('By keyword:')
            self.search_rad.setChecked(True)
            self.search_txt = QLineEdit()
            self.search_txt.returnPressed.connect(self.s_search)
            if default:
                self.search_txt.setText(default)
            self.search_btn = QPushButton('Search')
            self.search_btn.clicked.connect(self.s_search)
            top_layout.addWidget(self.search_rad)
            top_layout.addWidget(self.search_txt)
        else:
            top_layout.setAlignment(QtCore.Qt.AlignRight)

        top_layout.addWidget(self.search_btn)
        
        # Create filter line
        filters_layout = QHBoxLayout()
        
        if utils.SEARCH_METHOD_SEASON in search_methods:
            self.season_rad = QRadioButton('By season:')
            self.season_combo = QComboBox()
            self.season_combo.addItem('Winter', utils.SEASON_WINTER)
            self.season_combo.addItem('Spring', utils.SEASON_SPRING)
            self.season_combo.addItem('Summer', utils.SEASON_SUMMER)
            self.season_combo.addItem('Fall', utils.SEASON_FALL)
        
            self.season_year = QSpinBox()

            today = date.today()
            current_season = (today.month - 1) / 3

            self.season_year.setRange(1900, today.year)
            self.season_year.setValue(today.year)
            self.season_combo.setCurrentIndex(current_season)

            filters_layout.addWidget(self.season_rad)
            filters_layout.addWidget(self.season_combo)
            filters_layout.addWidget(self.season_year)
        
            filters_layout.setAlignment(QtCore.Qt.AlignLeft)
            filters_layout.addWidget(QSplitter())
        else:
            filters_layout.setAlignment(QtCore.Qt.AlignRight)
        
        view_combo = QComboBox()
        view_combo.addItem('Table view')
        view_combo.addItem('Card view')
        view_combo.currentIndexChanged.connect(self.s_change_view)
        
        filters_layout.addWidget(view_combo)

        # Create central content
        self.contents = QStackedWidget()
        
        # Set up views
        tableview = AddTableDetailsView(None, self.worker)
        tableview.changed.connect(self.s_selected)
        self.contents.addWidget(tableview)
        
        cardview = AddCardView(api_info=self.worker.engine.api_info)
        cardview.changed.connect(self.s_selected)
        cardview.activated.connect(self.s_show_details)
        self.contents.addWidget(cardview)
        
        # Use for testing
        #self.set_results([{'id': 1, 'title': 'Hola', 'image': 'https://omaera.org/icon.png'}])

        bottom_buttons = QDialogButtonBox()
        bottom_buttons.addButton("Cancel", QDialogButtonBox.RejectRole)
        self.add_btn = bottom_buttons.addButton("Add", QDialogButtonBox.AcceptRole)
        self.add_btn.setEnabled(False)
        bottom_buttons.accepted.connect(self.s_add)
        bottom_buttons.rejected.connect(self.close)

        # Finish layout
        layout.addLayout(top_layout)
        layout.addLayout(filters_layout)
        layout.addWidget(self.contents)
        layout.addWidget(bottom_buttons)
        self.setLayout(layout)

        if utils.SEARCH_METHOD_SEASON in search_methods:
            self.search_txt.setFocus()

    def worker_call(self, function, ret_function, *args, **kwargs):
        # Run worker in a thread
        self.worker.set_function(function, ret_function, *args, **kwargs)
        self.worker.start()

    def _enable_widgets(self, enable):
        self.search_btn.setEnabled(enable)
        self.contents.currentWidget().setEnabled(enable)

    def set_results(self, results):
        self.results = results
        self.contents.currentWidget().setResults(self.results)

    # Slots
    def s_show_details(self):
        detailswindow = DetailsDialog(self, self.worker, self.selected_show)
        detailswindow.setModal(True)
        detailswindow.show()

    def s_change_view(self, item):
        self.contents.currentWidget().getModel().setResults(None)
        self.contents.setCurrentIndex(item)
        self.contents.currentWidget().getModel().setResults(self.results)
        
    def s_search(self):
        if self.search_rad.isChecked():
            criteria = self.search_txt.text().strip()
            if not criteria:
                return
            method = utils.SEARCH_METHOD_KW
        elif self.season_rad.isChecked():
            criteria = (self.season_combo.itemData(self.season_combo.currentIndex()), self.season_year.value())
            method = utils.SEARCH_METHOD_SEASON
        
        self.contents.currentWidget().clearSelection()
        self.selected_show = None
        
        self._enable_widgets(False)
        self.add_btn.setEnabled(False)
        
        self.worker_call('search', self.r_searched, criteria, method)
    
    def s_selected(self, show):
        self.selected_show = show
        self.add_btn.setEnabled(True)
        
    def s_add(self):
        if self.selected_show:
            self.worker_call('add_show', self.r_added, self.selected_show, self.current_status)

    # Worker responses
    def r_searched(self, result):
        self._enable_widgets(True)
        
        if result['success']:
            self.set_results(result['result'])
            
            """
            if self.table.currentRow() is 0:  # Row number hasn't changed but the data probably has!
                self.s_show_selected(self.table.item(0, 0))
            self.table.setCurrentItem(self.table.item(0, 0))"""
        else:
            self.set_results(None)

    def r_added(self, result):
        if result['success']:
            if self.default:
                self.accept()
Пример #54
0
class PyMultiPageWidget(QWidget):

    currentIndexChanged = pyqtSignal(int)

    pageTitleChanged = pyqtSignal(str)

    def __init__(self, parent=None):
        super(PyMultiPageWidget, self).__init__(parent)

        self.comboBox = QComboBox()
        # MAGIC
        # It is important that the combo box has an object name beginning
        # with '__qt__passive_', otherwise, it is inactive in the form editor
        # of the designer and you can't change the current page via the
        # combo box.
        # MAGIC
        self.comboBox.setObjectName('__qt__passive_comboBox')        
        self.stackWidget = QStackedWidget()
        self.comboBox.activated.connect(self.setCurrentIndex)
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.comboBox)
        self.layout.addWidget(self.stackWidget)
        self.setLayout(self.layout)

    def sizeHint(self):
        return QSize(200, 150)

    def count(self):
        return self.stackWidget.count()

    def widget(self, index):
        return self.stackWidget.widget(index)

    @pyqtSlot(QWidget)
    def addPage(self, page):
        self.insertPage(self.count(), page)

    @pyqtSlot(int, QWidget)
    def insertPage(self, index, page):
        page.setParent(self.stackWidget)
        self.stackWidget.insertWidget(index, page)
        title = page.windowTitle()
        if title == "":
            title = "Page %d" % (self.comboBox.count() + 1)
            page.setWindowTitle(title)
        self.comboBox.insertItem(index, title)

    @pyqtSlot(int)
    def removePage(self, index):
        widget = self.stackWidget.widget(index)
        self.stackWidget.removeWidget(widget)
        self.comboBox.removeItem(index)

    def getPageTitle(self):
        return self.stackWidget.currentWidget().windowTitle()
    
    @pyqtSlot(str)
    def setPageTitle(self, newTitle):
        self.comboBox.setItemText(self.getCurrentIndex(), newTitle)
        self.stackWidget.currentWidget().setWindowTitle(newTitle)
        self.pageTitleChanged.emit(newTitle)

    def getCurrentIndex(self):
        return self.stackWidget.currentIndex()

    @pyqtSlot(int)
    def setCurrentIndex(self, index):
        if index != self.getCurrentIndex():
            self.stackWidget.setCurrentIndex(index)
            self.comboBox.setCurrentIndex(index)
            self.currentIndexChanged.emit(index)

    pageTitle = pyqtProperty(str, fget=getPageTitle, fset=setPageTitle, stored=False)
    currentIndex = pyqtProperty(int, fget=getCurrentIndex, fset=setCurrentIndex)
Пример #55
0
class SettingsDialog(QDialog):
    def __init__(self, settings_object, parent=None):
        super().__init__(parent)

        # The settings object should not be changed directly. Use enqueue_change() to set values and call
        # commit_changes() to write them to file when the user clicks either the "Ok" or "Apply" button.
        self.settings_object = settings_object
        self.pending_changes = {}

        # A list of different settings groups, categorized by the application they apply to.
        self.category_list = QListWidget()
        self.category_list.setSpacing(3)
        self.category_list.setMaximumWidth(100)
        handlebar_category = QListWidgetItem(self.category_list)
        handlebar_category.setText('General')
        handbrake_category = QListWidgetItem(self.category_list)
        handbrake_category.setText('Encoder')
        handbrake_category = QListWidgetItem(self.category_list)
        handbrake_category.setText('Output')

        self.category_pages = QStackedWidget()
        self.category_pages.addWidget(GeneralSettingsPage(self, settings_object))
        self.category_pages.addWidget(EncoderSettingsPage(self, settings_object))
        self.category_pages.addWidget(OutputSettingsPage(self, settings_object))

        self.category_list.setCurrentRow(0)
        self.category_list.currentItemChanged.connect(self.change_category)

        category_layout = QHBoxLayout()
        category_layout.addWidget(self.category_list)
        category_layout.addWidget(self.category_pages)

        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Cancel')
        self.apply_button = QPushButton('Apply')
        self.apply_button.setEnabled(False)

        ok_button.clicked.connect(self.commit_changes_and_close)
        cancel_button.clicked.connect(self.close)
        self.apply_button.clicked.connect(self.commit_changes)

        button_bar_layout = QHBoxLayout()
        button_bar_layout.addStretch(1)
        button_bar_layout.addWidget(ok_button)
        button_bar_layout.addWidget(cancel_button)
        button_bar_layout.addWidget(self.apply_button)

        main_layout = QVBoxLayout()
        main_layout.addLayout(category_layout)
        main_layout.addLayout(button_bar_layout)
        self.setLayout(main_layout)

        self.setWindowTitle('Configure Settings')
        self.resize(600, 300)

    def change_category(self, current, previous):
        if not current:
            current = previous

        self.category_pages.setCurrentIndex(self.category_list.row(current))

    def commit_changes_and_close(self):
        """Convenience function that calls commit_changes and then closes the dialog. Used by the "OK" button"""
        self.commit_changes()
        self.close()

    def commit_changes(self):
        if len(self.pending_changes) > 0:
            print('Settings committed to file.')
            self.settings_object.read_dict(self.pending_changes)
            self.settings_object.save()
            self.pending_changes = {}
            self.apply_button.setEnabled(False)  # There are no longer any pending changes.

    def enqueue_change(self, category, name, value):
        print('Setting "{}" changed to {}.'.format(name, value))
        if category in self.pending_changes.keys():  # If a nested dict already exists for this category:
            self.pending_changes[category][name] = value  # Add this pair to the nested dict.
        else:
            self.pending_changes[category] = {name: value}  # Create the nested dict with this pair.
        self.apply_button.setEnabled(True)  # There are now pending changes that can be applied.
Пример #56
0
class Window(QMainWindow):

    BOARD_HEIGHT = 621
    BOARD_WIDTH = 1000

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

        self.widgMain = MainForm()
        self.widgTeam = TeamSelectionUI()
        self.widgBoard = Board()
        print("AFTER BOARD CREATED")
        self.server = Server()

        # Set up signal to allow state change
        self.server.updateActiveWidget.connect(self.updateActiveWidget)

        # Set up signal to allow data to be sent to MAIN_SCREEN
        self.server.updateConnectedUsersSig.connect(self.widgMain.updateConnectedUsers)
        self.server.appendConnectedHistorySig.connect(self.widgMain.appendConnectedHistory)
        self.server.updateConnectedUsersSig.connect(self.widgMain.updateConnectedHistory)
        self.server.updateGameInfoSig.connect(self.widgMain.updateGameInfo)

        """ Set up signal to allow data to be received by the TEAM_SCREEN (self.widgTeam), data sent is used to sort
        clients into teams of two
        """
        self.server.setupTeamSig.connect(self.widgTeam.setupTeam)


        # Set up signal to allow data to be sent to GAME_SCREEN
        self.server.updateGameSig.connect(self.widgBoard.updateGame)

        # Set up signal to allow updated teams to be sent to server
        self.widgTeam.updateTeamsSig.connect(self.server.updateTeams)

        self.stack = QStackedWidget(self)
        self.stack.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT)
        self.stack.addWidget(self.widgMain)
        self.stack.addWidget(self.widgTeam)
        self.stack.addWidget(self.widgBoard)

        self.resize(self.BOARD_WIDTH, self.BOARD_HEIGHT)

        layout = QGridLayout()
        layout.addWidget(self.stack)
        self.setLayout(layout)

        self.setWindowTitle("Blobbageddon")

        self.stack.setCurrentIndex(0)

        self.server.start()
        self.show()

    def updateActiveWidget(self, adrs):
        if (self.server.state.currState == State.GAME_SCREEN):
            self.stack.setCurrentIndex(2)
            print(len(adrs))
            self.widgBoard.start(adrs)
        elif self.server.state.currState == State.TEAM_SCREEN:
            self.widgTeam.setupUi(adrs)
            self.stack.setCurrentIndex(1)
        elif (self.server.state.currState == State.MAIN_SCREEN):
            self.stack.setCurrentIndex(0)
Пример #57
0
class Settings(QDialog):
    """Window showing the Settings/settings.

    Parameters
    ----------
    parent : instance of QMainWindow
        the main window
    """
    def __init__(self, parent):
        super().__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.parent = parent
        self.config = ConfigUtils(self.parent.update)

        self.setWindowTitle('Settings')
        self.create_settings()

    def create_settings(self):
        """Create the widget, organized in two parts.

        Notes
        -----
        When you add widgets in config, remember to update show_settings too
        """
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply |
                                QDialogButtonBox.Cancel)
        self.idx_ok = bbox.button(QDialogButtonBox.Ok)
        self.idx_apply = bbox.button(QDialogButtonBox.Apply)
        self.idx_cancel = bbox.button(QDialogButtonBox.Cancel)
        bbox.clicked.connect(self.button_clicked)

        page_list = QListWidget()
        page_list.setSpacing(1)
        page_list.currentRowChanged.connect(self.change_widget)

        pages = ['General', 'Overview', 'Signals', 'Channels', 'Spectrum',
                 'Notes', 'Video']
        for one_page in pages:
            page_list.addItem(one_page)

        self.stacked = QStackedWidget()
        self.stacked.addWidget(self.config)
        self.stacked.addWidget(self.parent.overview.config)
        self.stacked.addWidget(self.parent.traces.config)
        self.stacked.addWidget(self.parent.channels.config)
        self.stacked.addWidget(self.parent.spectrum.config)
        self.stacked.addWidget(self.parent.notes.config)
        self.stacked.addWidget(self.parent.video.config)

        hsplitter = QSplitter()
        hsplitter.addWidget(page_list)
        hsplitter.addWidget(self.stacked)

        btnlayout = QHBoxLayout()
        btnlayout.addStretch(1)
        btnlayout.addWidget(bbox)

        vlayout = QVBoxLayout()
        vlayout.addWidget(hsplitter)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

    def change_widget(self, new_row):
        """Change the widget on the right side.

        Parameters
        ----------
        new_row : int
            index of the widgets
        """
        self.stacked.setCurrentIndex(new_row)

    def button_clicked(self, button):
        """Action when button was clicked.

        Parameters
        ----------
        button : instance of QPushButton
            which button was pressed
        """
        if button in (self.idx_ok, self.idx_apply):

            # loop over widgets, to see if they were modified
            for i_config in range(self.stacked.count()):
                one_config = self.stacked.widget(i_config)

                if one_config.modified:
                    lg.debug('Settings for ' + one_config.widget +
                             ' were modified')
                    one_config.get_values()

                    if self.parent.info.dataset is not None:
                        one_config.update_widget()
                    one_config.modified = False

            if button == self.idx_ok:
                self.accept()

        if button == self.idx_cancel:
            self.reject()
Пример #58
0
class SettingsDialog(QDialog):
    worker = None
    config = None
    configfile = None

    saved = QtCore.pyqtSignal()

    def __init__(self, parent, worker, config, configfile):
        QDialog.__init__(self, parent)

        self.worker = worker
        self.config = config
        self.configfile = configfile
        self.setStyleSheet("QGroupBox { font-weight: bold; } ")
        self.setWindowTitle('Settings')
        layout = QGridLayout()

        # Categories
        self.category_list = QListWidget()
        category_media = QListWidgetItem(getIcon('media-playback-start'), 'Media', self.category_list)
        category_sync = QListWidgetItem(getIcon('view-refresh'), 'Sync', self.category_list)
        category_ui = QListWidgetItem(getIcon('window-new'), 'User Interface', self.category_list)
        category_theme = QListWidgetItem(getIcon('applications-graphics'), 'Theme', self.category_list)
        self.category_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self.category_list.setCurrentRow(0)
        self.category_list.setMaximumWidth(self.category_list.sizeHintForColumn(0) + 15)
        self.category_list.setFocus()
        self.category_list.currentItemChanged.connect(self.s_switch_page)

        # Media tab
        page_media = QWidget()
        page_media_layout = QVBoxLayout()
        page_media_layout.setAlignment(QtCore.Qt.AlignTop)

        # Group: Media settings
        g_media = QGroupBox('Media settings')
        g_media.setFlat(True)
        g_media_layout = QFormLayout()
        self.tracker_enabled = QCheckBox()
        self.tracker_enabled.toggled.connect(self.tracker_type_change)

        self.tracker_type = QComboBox()
        for (n, label) in utils.available_trackers:
            self.tracker_type.addItem(label, n)
        self.tracker_type.currentIndexChanged.connect(self.tracker_type_change)

        self.tracker_interval = QSpinBox()
        self.tracker_interval.setRange(5, 1000)
        self.tracker_interval.setMaximumWidth(60)
        self.tracker_process = QLineEdit()
        self.tracker_update_wait = QSpinBox()
        self.tracker_update_wait.setRange(0, 1000)
        self.tracker_update_wait.setMaximumWidth(60)
        self.tracker_update_close = QCheckBox()
        self.tracker_update_prompt = QCheckBox()
        self.tracker_not_found_prompt = QCheckBox()

        g_media_layout.addRow('Enable tracker', self.tracker_enabled)
        g_media_layout.addRow('Tracker type', self.tracker_type)
        g_media_layout.addRow('Tracker interval (seconds)', self.tracker_interval)
        g_media_layout.addRow('Process name (regex)', self.tracker_process)
        g_media_layout.addRow('Wait before updating (seconds)', self.tracker_update_wait)
        g_media_layout.addRow('Wait until the player is closed', self.tracker_update_close)
        g_media_layout.addRow('Ask before updating', self.tracker_update_prompt)
        g_media_layout.addRow('Ask to add new shows', self.tracker_not_found_prompt)

        g_media.setLayout(g_media_layout)

        # Group: Plex settings
        g_plex = QGroupBox('Plex Media Server')
        g_plex.setFlat(True)
        self.plex_host = QLineEdit()
        self.plex_port = QLineEdit()
        self.plex_user = QLineEdit()
        self.plex_passw = QLineEdit()
        self.plex_passw.setEchoMode(QLineEdit.Password)
        self.plex_obey_wait = QCheckBox()

        g_plex_layout = QGridLayout()
        g_plex_layout.addWidget(QLabel('Host and Port'),                   0, 0, 1, 1)
        g_plex_layout.addWidget(self.plex_host,                            0, 1, 1, 1)
        g_plex_layout.addWidget(self.plex_port,                            0, 2, 1, 2)
        g_plex_layout.addWidget(QLabel('Use "wait before updating" time'), 1, 0, 1, 1)
        g_plex_layout.addWidget(self.plex_obey_wait,                       1, 2, 1, 1)
        g_plex_layout.addWidget(QLabel('myPlex login (claimed server)'),   2, 0, 1, 1)
        g_plex_layout.addWidget(self.plex_user,                            2, 1, 1, 1)
        g_plex_layout.addWidget(self.plex_passw,                           2, 2, 1, 2)

        g_plex.setLayout(g_plex_layout)

        # Group: Library
        g_playnext = QGroupBox('Library')
        g_playnext.setFlat(True)
        self.player = QLineEdit()
        self.player_browse = QPushButton('Browse...')
        self.player_browse.clicked.connect(self.s_player_browse)
        lbl_searchdirs = QLabel('Media directories')
        lbl_searchdirs.setAlignment(QtCore.Qt.AlignTop)
        self.searchdirs = QListWidget()
        self.searchdirs_add = QPushButton('Add...')
        self.searchdirs_add.clicked.connect(self.s_searchdirs_add)
        self.searchdirs_remove = QPushButton('Remove')
        self.searchdirs_remove.clicked.connect(self.s_searchdirs_remove)
        self.searchdirs_buttons = QVBoxLayout()
        self.searchdirs_buttons.setAlignment(QtCore.Qt.AlignTop)
        self.searchdirs_buttons.addWidget(self.searchdirs_add)
        self.searchdirs_buttons.addWidget(self.searchdirs_remove)
        self.searchdirs_buttons.addWidget(QSplitter())
        self.library_autoscan = QCheckBox()
        self.scan_whole_list = QCheckBox()
        self.library_full_path = QCheckBox()


        g_playnext_layout = QGridLayout()
        g_playnext_layout.addWidget(QLabel('Player'),                    0, 0, 1, 1)
        g_playnext_layout.addWidget(self.player,                         0, 1, 1, 1)
        g_playnext_layout.addWidget(self.player_browse,                  0, 2, 1, 1)
        g_playnext_layout.addWidget(lbl_searchdirs,                      1, 0, 1, 1)
        g_playnext_layout.addWidget(self.searchdirs,                     1, 1, 1, 1)
        g_playnext_layout.addLayout(self.searchdirs_buttons,             1, 2, 1, 1)
        g_playnext_layout.addWidget(QLabel('Rescan Library at startup'), 2, 0, 1, 2)
        g_playnext_layout.addWidget(self.library_autoscan,               2, 2, 1, 1)
        g_playnext_layout.addWidget(QLabel('Scan through whole list'),   3, 0, 1, 2)
        g_playnext_layout.addWidget(self.scan_whole_list,                3, 2, 1, 1)
        g_playnext_layout.addWidget(QLabel('Take subdirectory name into account'), 4, 0, 1, 2)
        g_playnext_layout.addWidget(self.library_full_path,              4, 2, 1, 1)

        g_playnext.setLayout(g_playnext_layout)

        # Media form
        page_media_layout.addWidget(g_media)
        page_media_layout.addWidget(g_plex)
        page_media_layout.addWidget(g_playnext)
        page_media.setLayout(page_media_layout)

        # Sync tab
        page_sync = QWidget()
        page_sync_layout = QVBoxLayout()
        page_sync_layout.setAlignment(QtCore.Qt.AlignTop)

        # Group: Autoretrieve
        g_autoretrieve = QGroupBox('Autoretrieve')
        g_autoretrieve.setFlat(True)
        self.autoretrieve_off = QRadioButton('Disabled')
        self.autoretrieve_always = QRadioButton('Always at start')
        self.autoretrieve_days = QRadioButton('After n days')
        self.autoretrieve_days.toggled.connect(self.s_autoretrieve_days)
        self.autoretrieve_days_n = QSpinBox()
        self.autoretrieve_days_n.setRange(1, 100)
        g_autoretrieve_layout = QGridLayout()
        g_autoretrieve_layout.setColumnStretch(0, 1)
        g_autoretrieve_layout.addWidget(self.autoretrieve_off,    0, 0, 1, 1)
        g_autoretrieve_layout.addWidget(self.autoretrieve_always, 1, 0, 1, 1)
        g_autoretrieve_layout.addWidget(self.autoretrieve_days,   2, 0, 1, 1)
        g_autoretrieve_layout.addWidget(self.autoretrieve_days_n, 2, 1, 1, 1)
        g_autoretrieve.setLayout(g_autoretrieve_layout)

        # Group: Autosend
        g_autosend = QGroupBox('Autosend')
        g_autosend.setFlat(True)
        self.autosend_off = QRadioButton('Disabled')
        self.autosend_always = QRadioButton('Immediately after every change')
        self.autosend_minutes = QRadioButton('After n minutes')
        self.autosend_minutes.toggled.connect(self.s_autosend_minutes)
        self.autosend_minutes_n = QSpinBox()
        self.autosend_minutes_n.setRange(1, 1000)
        self.autosend_size = QRadioButton('After the queue reaches n items')
        self.autosend_size.toggled.connect(self.s_autosend_size)
        self.autosend_size_n = QSpinBox()
        self.autosend_size_n.setRange(2, 20)
        self.autosend_at_exit = QCheckBox('At exit')
        g_autosend_layout = QGridLayout()
        g_autosend_layout.setColumnStretch(0, 1)
        g_autosend_layout.addWidget(self.autosend_off,      0, 0, 1, 1)
        g_autosend_layout.addWidget(self.autosend_always,   1, 0, 1, 1)
        g_autosend_layout.addWidget(self.autosend_minutes,    2, 0, 1, 1)
        g_autosend_layout.addWidget(self.autosend_minutes_n,  2, 1, 1, 1)
        g_autosend_layout.addWidget(self.autosend_size,     3, 0, 1, 1)
        g_autosend_layout.addWidget(self.autosend_size_n,   3, 1, 1, 1)
        g_autosend_layout.addWidget(self.autosend_at_exit,  4, 0, 1, 1)
        g_autosend.setLayout(g_autosend_layout)

        # Group: Extra
        g_extra = QGroupBox('Additional options')
        g_extra.setFlat(True)
        self.auto_status_change = QCheckBox('Change status automatically')
        self.auto_status_change.toggled.connect(self.s_auto_status_change)
        self.auto_status_change_if_scored = QCheckBox('Change status automatically only if scored')
        self.auto_date_change = QCheckBox('Change start and finish dates automatically')
        g_extra_layout = QVBoxLayout()
        g_extra_layout.addWidget(self.auto_status_change)
        g_extra_layout.addWidget(self.auto_status_change_if_scored)
        g_extra_layout.addWidget(self.auto_date_change)
        g_extra.setLayout(g_extra_layout)

        # Sync layout
        page_sync_layout.addWidget(g_autoretrieve)
        page_sync_layout.addWidget(g_autosend)
        page_sync_layout.addWidget(g_extra)
        page_sync.setLayout(page_sync_layout)

        # UI tab
        page_ui = QWidget()
        page_ui_layout = QFormLayout()
        page_ui_layout.setAlignment(QtCore.Qt.AlignTop)

        # Group: Icon
        g_icon = QGroupBox('Notification Icon')
        g_icon.setFlat(True)
        self.tray_icon = QCheckBox('Show tray icon')
        self.tray_icon.toggled.connect(self.s_tray_icon)
        self.close_to_tray = QCheckBox('Close to tray')
        self.start_in_tray = QCheckBox('Start minimized to tray')
        self.tray_api_icon = QCheckBox('Use API icon as tray icon')
        self.notifications = QCheckBox('Show notification when tracker detects new media')
        g_icon_layout = QVBoxLayout()
        g_icon_layout.addWidget(self.tray_icon)
        g_icon_layout.addWidget(self.close_to_tray)
        g_icon_layout.addWidget(self.start_in_tray)
        g_icon_layout.addWidget(self.tray_api_icon)
        g_icon_layout.addWidget(self.notifications)
        g_icon.setLayout(g_icon_layout)

        # Group: Window
        g_window = QGroupBox('Window')
        g_window.setFlat(True)
        self.remember_geometry = QCheckBox('Remember window size and position')
        self.remember_columns = QCheckBox('Remember column layouts and widths')
        self.columns_per_api = QCheckBox('Use different visible columns per API')
        g_window_layout = QVBoxLayout()
        g_window_layout.addWidget(self.remember_geometry)
        g_window_layout.addWidget(self.remember_columns)
        g_window_layout.addWidget(self.columns_per_api)
        g_window.setLayout(g_window_layout)

        # Group: Lists
        g_lists = QGroupBox('Lists')
        g_lists.setFlat(True)
        self.filter_bar_position = QComboBox()
        filter_bar_positions = [(FilterBar.PositionHidden,     'Hidden'),
                                (FilterBar.PositionAboveLists, 'Above lists'),
                                (FilterBar.PositionBelowLists, 'Below lists')]
        for (n, label) in filter_bar_positions:
            self.filter_bar_position.addItem(label, n)
        self.inline_edit = QCheckBox('Enable in-line editing')
        g_lists_layout = QFormLayout()
        g_lists_layout.addRow('Filter bar position:', self.filter_bar_position)
        g_lists_layout.addRow(self.inline_edit)
        g_lists.setLayout(g_lists_layout)

        # UI layout
        page_ui_layout.addWidget(g_icon)
        page_ui_layout.addWidget(g_window)
        page_ui_layout.addWidget(g_lists)
        page_ui.setLayout(page_ui_layout)

        # Theming tab
        page_theme = QWidget()
        page_theme_layout = QFormLayout()
        page_theme_layout.setAlignment(QtCore.Qt.AlignTop)

        # Group: Episode Bar
        g_ep_bar = QGroupBox('Episode Bar')
        g_ep_bar.setFlat(True)
        self.ep_bar_style = QComboBox()
        ep_bar_styles = [(ShowsTableDelegate.BarStyleBasic,  'Basic'),
                         (ShowsTableDelegate.BarStyle04,     'Trackma'),
                         (ShowsTableDelegate.BarStyleHybrid, 'Hybrid')]
        for (n, label) in ep_bar_styles:
            self.ep_bar_style.addItem(label, n)
        self.ep_bar_style.currentIndexChanged.connect(self.s_ep_bar_style)
        self.ep_bar_text = QCheckBox('Show text label')
        g_ep_bar_layout = QFormLayout()
        g_ep_bar_layout.addRow('Style:', self.ep_bar_style)
        g_ep_bar_layout.addRow(self.ep_bar_text)
        g_ep_bar.setLayout(g_ep_bar_layout)

        # Group: Colour scheme
        g_scheme = QGroupBox('Color Scheme')
        g_scheme.setFlat(True)
        col_tabs = [('rows',     '&Row highlights'),
                    ('progress', '&Progress widget')]
        self.colors = {}
        self.colors['rows'] = [('is_playing',  'Playing'),
                               ('is_queued',   'Queued'),
                               ('new_episode', 'New Episode'),
                               ('is_airing',   'Airing'),
                               ('not_aired',   'Unaired')]
        self.colors['progress'] = [('progress_bg',       'Background'),
                                   ('progress_fg',       'Watched bar'),
                                   ('progress_sub_bg',   'Aired episodes'),
                                   ('progress_sub_fg',   'Stored episodes'),
                                   ('progress_complete', 'Complete')]
        self.color_buttons = []
        self.syscolor_buttons = []
        g_scheme_layout = QGridLayout()
        tw_scheme = QTabWidget()
        for (key, tab_title) in col_tabs:
            page = QFrame()
            page_layout = QGridLayout()
            col = 0
            # Generate widgets from the keys and values
            for (key, label) in self.colors[key]:
                self.color_buttons.append(QPushButton())
                # self.color_buttons[-1].setStyleSheet('background-color: ' + getColor(self.config['colors'][key]).name())
                self.color_buttons[-1].setFocusPolicy(QtCore.Qt.NoFocus)
                self.color_buttons[-1].clicked.connect(self.s_color_picker(key, False))
                self.syscolor_buttons.append(QPushButton('System Colors'))
                self.syscolor_buttons[-1].clicked.connect(self.s_color_picker(key, True))
                page_layout.addWidget(QLabel(label),             col, 0, 1, 1)
                page_layout.addWidget(self.color_buttons[-1],    col, 1, 1, 1)
                page_layout.addWidget(self.syscolor_buttons[-1], col, 2, 1, 1)
                col += 1
            page.setLayout(page_layout)
            tw_scheme.addTab(page, tab_title)
        g_scheme_layout.addWidget(tw_scheme)
        g_scheme.setLayout(g_scheme_layout)

        # UI layout
        page_theme_layout.addWidget(g_ep_bar)
        page_theme_layout.addWidget(g_scheme)
        page_theme.setLayout(page_theme_layout)

        # Content
        self.contents = QStackedWidget()
        self.contents.addWidget(page_media)
        self.contents.addWidget(page_sync)
        self.contents.addWidget(page_ui)
        self.contents.addWidget(page_theme)
        if pyqt_version is not 5:
            self.contents.layout().setMargin(0)

        # Bottom buttons
        bottombox = QDialogButtonBox(
            QDialogButtonBox.Ok
            | QDialogButtonBox.Apply
            | QDialogButtonBox.Cancel
        )
        bottombox.accepted.connect(self.s_save)
        bottombox.button(QDialogButtonBox.Apply).clicked.connect(self._save)
        bottombox.rejected.connect(self.reject)

        # Main layout finish
        layout.addWidget(self.category_list,  0, 0, 1, 1)
        layout.addWidget(self.contents,       0, 1, 1, 1)
        layout.addWidget(bottombox,           1, 0, 1, 2)
        layout.setColumnStretch(1, 1)

        self._load()
        self.update_colors()

        self.setLayout(layout)

    def _add_dir(self, path):
        self.searchdirs.addItem(path)

    def _load(self):
        engine = self.worker.engine
        tracker_type = self.tracker_type.findData(engine.get_config('tracker_type'))
        autoretrieve = engine.get_config('autoretrieve')
        autosend = engine.get_config('autosend')

        self.tracker_enabled.setChecked(engine.get_config('tracker_enabled'))
        self.tracker_type.setCurrentIndex(max(0, tracker_type))
        self.tracker_interval.setValue(engine.get_config('tracker_interval'))
        self.tracker_process.setText(engine.get_config('tracker_process'))
        self.tracker_update_wait.setValue(engine.get_config('tracker_update_wait_s'))
        self.tracker_update_close.setChecked(engine.get_config('tracker_update_close'))
        self.tracker_update_prompt.setChecked(engine.get_config('tracker_update_prompt'))
        self.tracker_not_found_prompt.setChecked(engine.get_config('tracker_not_found_prompt'))

        self.player.setText(engine.get_config('player'))
        self.library_autoscan.setChecked(engine.get_config('library_autoscan'))
        self.scan_whole_list.setChecked(engine.get_config('scan_whole_list'))
        self.library_full_path.setChecked(engine.get_config('library_full_path'))
        self.plex_host.setText(engine.get_config('plex_host'))
        self.plex_port.setText(engine.get_config('plex_port'))
        self.plex_obey_wait.setChecked(engine.get_config('plex_obey_update_wait_s'))
        self.plex_user.setText(engine.get_config('plex_user'))
        self.plex_passw.setText(engine.get_config('plex_passwd'))

        for path in engine.get_config('searchdir'):
            self._add_dir(path)

        if autoretrieve == 'always':
            self.autoretrieve_always.setChecked(True)
        elif autoretrieve == 'days':
            self.autoretrieve_days.setChecked(True)
        else:
            self.autoretrieve_off.setChecked(True)

        self.autoretrieve_days_n.setValue(engine.get_config('autoretrieve_days'))

        if autosend == 'always':
            self.autosend_always.setChecked(True)
        elif autosend in ('minutes', 'hours'):
            self.autosend_minutes.setChecked(True)
        elif autosend == 'size':
            self.autosend_size.setChecked(True)
        else:
            self.autosend_off.setChecked(True)

        self.autosend_minutes_n.setValue(engine.get_config('autosend_minutes'))
        self.autosend_size_n.setValue(engine.get_config('autosend_size'))

        self.autosend_at_exit.setChecked(engine.get_config('autosend_at_exit'))
        self.auto_status_change.setChecked(engine.get_config('auto_status_change'))
        self.auto_status_change_if_scored.setChecked(engine.get_config('auto_status_change_if_scored'))
        self.auto_date_change.setChecked(engine.get_config('auto_date_change'))

        self.tray_icon.setChecked(self.config['show_tray'])
        self.close_to_tray.setChecked(self.config['close_to_tray'])
        self.start_in_tray.setChecked(self.config['start_in_tray'])
        self.tray_api_icon.setChecked(self.config['tray_api_icon'])
        self.notifications.setChecked(self.config['notifications'])
        self.remember_geometry.setChecked(self.config['remember_geometry'])
        self.remember_columns.setChecked(self.config['remember_columns'])
        self.columns_per_api.setChecked(self.config['columns_per_api'])
        self.filter_bar_position.setCurrentIndex(self.filter_bar_position.findData(self.config['filter_bar_position']))
        self.inline_edit.setChecked(self.config['inline_edit'])

        self.ep_bar_style.setCurrentIndex(self.ep_bar_style.findData(self.config['episodebar_style']))
        self.ep_bar_text.setChecked(self.config['episodebar_text'])

        self.autoretrieve_days_n.setEnabled(self.autoretrieve_days.isChecked())
        self.autosend_minutes_n.setEnabled(self.autosend_minutes.isChecked())
        self.autosend_size_n.setEnabled(self.autosend_size.isChecked())
        self.close_to_tray.setEnabled(self.tray_icon.isChecked())
        self.start_in_tray.setEnabled(self.tray_icon.isChecked())
        self.notifications.setEnabled(self.tray_icon.isChecked())

        self.color_values = self.config['colors'].copy()

        self.tracker_type_change(None)

    def _save(self):
        engine = self.worker.engine

        engine.set_config('tracker_enabled',       self.tracker_enabled.isChecked())
        engine.set_config('tracker_type',          self.tracker_type.itemData(self.tracker_type.currentIndex()))
        engine.set_config('tracker_interval',      self.tracker_interval.value())
        engine.set_config('tracker_process',       str(self.tracker_process.text()))
        engine.set_config('tracker_update_wait_s', self.tracker_update_wait.value())
        engine.set_config('tracker_update_close',  self.tracker_update_close.isChecked())
        engine.set_config('tracker_update_prompt', self.tracker_update_prompt.isChecked())
        engine.set_config('tracker_not_found_prompt', self.tracker_not_found_prompt.isChecked())

        engine.set_config('player',            self.player.text())
        engine.set_config('library_autoscan',  self.library_autoscan.isChecked())
        engine.set_config('scan_whole_list', self.scan_whole_list.isChecked())
        engine.set_config('library_full_path', self.library_full_path.isChecked())
        engine.set_config('plex_host',         self.plex_host.text())
        engine.set_config('plex_port',         self.plex_port.text())
        engine.set_config('plex_obey_update_wait_s', self.plex_obey_wait.isChecked())
        engine.set_config('plex_user',         self.plex_user.text())
        engine.set_config('plex_passwd',       self.plex_passw.text())

        engine.set_config('searchdir',         [self.searchdirs.item(i).text() for i in range(self.searchdirs.count())])

        if self.autoretrieve_always.isChecked():
            engine.set_config('autoretrieve', 'always')
        elif self.autoretrieve_days.isChecked():
            engine.set_config('autoretrieve', 'days')
        else:
            engine.set_config('autoretrieve', 'off')

        engine.set_config('autoretrieve_days',   self.autoretrieve_days_n.value())

        if self.autosend_always.isChecked():
            engine.set_config('autosend', 'always')
        elif self.autosend_minutes.isChecked():
            engine.set_config('autosend', 'minutes')
        elif self.autosend_size.isChecked():
            engine.set_config('autosend', 'size')
        else:
            engine.set_config('autosend', 'off')

        engine.set_config('autosend_minutes', self.autosend_minutes_n.value())
        engine.set_config('autosend_size',  self.autosend_size_n.value())

        engine.set_config('autosend_at_exit',   self.autosend_at_exit.isChecked())
        engine.set_config('auto_status_change', self.auto_status_change.isChecked())
        engine.set_config('auto_status_change_if_scored', self.auto_status_change_if_scored.isChecked())
        engine.set_config('auto_date_change',   self.auto_date_change.isChecked())

        engine.save_config()

        self.config['show_tray'] = self.tray_icon.isChecked()
        self.config['close_to_tray'] = self.close_to_tray.isChecked()
        self.config['start_in_tray'] = self.start_in_tray.isChecked()
        self.config['tray_api_icon'] = self.tray_api_icon.isChecked()
        self.config['notifications'] = self.notifications.isChecked()
        self.config['remember_geometry'] = self.remember_geometry.isChecked()
        self.config['remember_columns'] = self.remember_columns.isChecked()
        self.config['columns_per_api'] = self.columns_per_api.isChecked()
        self.config['filter_bar_position'] = self.filter_bar_position.itemData(self.filter_bar_position.currentIndex())
        self.config['inline_edit'] = self.inline_edit.isChecked()

        self.config['episodebar_style'] = self.ep_bar_style.itemData(self.ep_bar_style.currentIndex())
        self.config['episodebar_text'] = self.ep_bar_text.isChecked()

        self.config['colors'] = self.color_values

        utils.save_config(self.config, self.configfile)

        self.saved.emit()

    def s_save(self):
        self._save()
        self.accept()

    def tracker_type_change(self, checked):
        if self.tracker_enabled.isChecked():
            self.tracker_interval.setEnabled(True)
            self.tracker_update_wait.setEnabled(True)
            self.tracker_type.setEnabled(True)
            if self.tracker_type.itemData(self.tracker_type.currentIndex()) == 'plex':
                self.plex_host.setEnabled(True)
                self.plex_port.setEnabled(True)
                self.plex_obey_wait.setEnabled(True)
                self.plex_user.setEnabled(True)
                self.plex_passw.setEnabled(True)
                self.tracker_process.setEnabled(False)
            else:
                self.tracker_process.setEnabled(True)
                self.plex_host.setEnabled(False)
                self.plex_port.setEnabled(False)
                self.plex_user.setEnabled(False)
                self.plex_passw.setEnabled(False)
                self.plex_obey_wait.setEnabled(False)
        else:
            self.tracker_type.setEnabled(False)
            self.plex_host.setEnabled(False)
            self.plex_port.setEnabled(False)
            self.plex_user.setEnabled(False)
            self.plex_passw.setEnabled(False)
            self.plex_obey_wait.setEnabled(False)
            self.tracker_process.setEnabled(False)
            self.tracker_interval.setEnabled(False)
            self.tracker_update_wait.setEnabled(False)

    def s_autoretrieve_days(self, checked):
        self.autoretrieve_days_n.setEnabled(checked)

    def s_autosend_minutes(self, checked):
        self.autosend_minutes_n.setEnabled(checked)

    def s_autosend_size(self, checked):
        self.autosend_size_n.setEnabled(checked)

    def s_tray_icon(self, checked):
        self.close_to_tray.setEnabled(checked)
        self.start_in_tray.setEnabled(checked)
        self.tray_api_icon.setEnabled(checked)
        self.notifications.setEnabled(checked)

    def s_ep_bar_style(self, index):
        if self.ep_bar_style.itemData(index) == ShowsTableDelegate.BarStyle04:
            self.ep_bar_text.setEnabled(False)
        else:
            self.ep_bar_text.setEnabled(True)

    def s_auto_status_change(self, checked):
        self.auto_status_change_if_scored.setEnabled(checked)

    def s_player_browse(self):
        if pyqt_version is 5:
            self.player.setText(QFileDialog.getOpenFileName(caption='Choose player executable')[0])
        else:
            self.player.setText(QFileDialog.getOpenFileName(caption='Choose player executable'))

    def s_searchdirs_add(self):
        self._add_dir(QFileDialog.getExistingDirectory(caption='Choose media directory'))

    def s_searchdirs_remove(self):
        row = self.searchdirs.currentRow()
        if row != -1:
            self.searchdirs.takeItem(row)

    def s_switch_page(self, new, old):
        if not new:
            new = old

        self.contents.setCurrentIndex(self.category_list.row(new))

    def s_color_picker(self, key, system):
        return lambda: self.color_picker(key, system)

    def color_picker(self, key, system):
        if system is True:
            current = self.color_values[key]
            result = ThemedColorPicker.do()
            if result is not None and result is not current:
                self.color_values[key] = result
                self.update_colors()
        else:
            current = getColor(self.color_values[key])
            result = QColorDialog.getColor(current)
            if result.isValid() and result is not current:
                self.color_values[key] = str(result.name())
                self.update_colors()

    def update_colors(self):
        for ((key, label), color) in zip(self.colors['rows']+self.colors['progress'], self.color_buttons):
            color.setStyleSheet('background-color: ' + getColor(self.color_values[key]).name())
Пример #59
0
class EditAnnotWgt(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.main_window = parent

        # Widgets
        self.annotationTypesCbo     = QComboBox(self)
        self.newAnnotationBtn       = QPushButton('New', self)
        self.duplicateAnnotationBtn = QPushButton('Duplicate', self)
        self.deleteAnnotationBtn    = QPushButton('Delete', self)
        self.viewJSONBtn            = QPushButton('View JSON', self)
        self.saveAnnotationBtn      = QPushButton('Save', self)
        self.commentEdt             = QTextEdit('', self)

        self.editAnnotWgt = OrderedDict([("text",     EditAnnotTextWgt(self)), 
                                         ("figure",   EditAnnotFigureWgt(self)), 
                                         ("table",    EditAnnotTableWgt(self)), 
                                         ("equation", EditAnnotEquationWgt(self)), 
                                         ("position", EditAnnotPositionWgt(self)),
                                         ("null",     EditAnnotNullWgt(self))])

        # We use the list to as a redundancy of the list of keys in annotTypesDict
        # because we want these to be ordered. 
        self.annotTypeLst     = list(self.editAnnotWgt.keys())

        self.annotationTypesCbo.addItems(self.annotTypeLst)

        self.editAnnotStack = QStackedWidget(self)

        for annotType in self.annotTypeLst:
            self.editAnnotStack.addWidget(self.editAnnotWgt[annotType])

        # Layout
        self.editAnnotGroupBox = QGroupBox()
        gridAddAnnotations = QGridLayout(self.editAnnotGroupBox)
        gridAddAnnotations.addWidget(QLabel('Annotation type', self), 2, 0)
        gridAddAnnotations.addWidget(self.annotationTypesCbo, 2, 1)
        gridAddAnnotations.addWidget(self.saveAnnotationBtn, 2, 2)
        gridAddAnnotations.addWidget(self.deleteAnnotationBtn, 2, 3)
        gridAddAnnotations.addWidget(self.newAnnotationBtn, 2, 4)
        gridAddAnnotations.addWidget(self.duplicateAnnotationBtn, 2, 5)
        gridAddAnnotations.addWidget(self.viewJSONBtn, 2, 6)

        gridAddAnnotations.addWidget(self.editAnnotStack, 3, 0, 1, 7)

        gridAddAnnotations.addWidget(QLabel('Comment', self), 4, 0)
        gridAddAnnotations.addWidget(self.commentEdt, 4, 1, 1, 6)
        self.setLayout(gridAddAnnotations)

        # Signals
        self.saveAnnotationBtn.clicked.connect(self.saveAnnotation)
        self.newAnnotationBtn.clicked.connect(self.newAnnotation)
        self.duplicateAnnotationBtn.clicked.connect(self.duplicateAnnotation)
        self.viewJSONBtn.clicked.connect(self.viewJSON)
        self.deleteAnnotationBtn.clicked.connect(self.main_window.deleteAnnotation)
        self.commentEdt.textChanged.connect(self.annotationChanged)
        self.annotationTypesCbo.currentIndexChanged.connect(self.setCurrentStack)

        self.main_window.selectedAnnotationChangedConfirmed.connect(self.annotationSelectionChanged)
        for wgt in self.editAnnotWgt.values():
            self.main_window.selectedAnnotationChangedConfirmed.connect(wgt.annotationSelectionChanged)
        self.main_window.annotationCleared.connect(self.clearAddAnnotation)
        self.main_window.savingNeeded.connect(self.savingNeeded)

        # Initial behavior
        self.deleteAnnotationBtn.setDisabled(True)
        self.viewJSONBtn.setDisabled(True)
        self.annotationTypesCbo.setCurrentIndex(0)
        self.setCurrentStack(0)
        self.annotationTypesCbo.setDisabled(True)

    def viewJSON(self):        
        form = JSONDlg()
        form.setJSON(self.currentAnnotation)
        if form.exec_() == QDialog.Accepted:
            return 

    def saveAnnotation(self):
        self.main_window.saveAnnotation()
        self.annotationTypesCbo.setDisabled(True)

        
    def selectAnnotType(self, annotType):
        
        ind = [no for no, a in enumerate(self.annotTypeLst) if a == annotType]
        if len(ind) != 1:
            raise ValueError("Invalid annotation type string.")
        ind = ind[0]

        self.annotationTypesCbo.setCurrentIndex(ind)
        self.annotationTypesCbo.setEnabled(False)


    def setCurrentStack(self, ind):
        self.editAnnotStack.setCurrentIndex(ind) 

        #for no in range(len(self.annotTypeLst)):
        #    self.editAnnotStack.setTabEnabled(no, no == ind)
    


    @pyqtSlot()
    def clearAddAnnotation(self):
        self.commentEdt.setText("")
        for widget in self.editAnnotWgt.values():
            widget.clearAnnotation()

    @property
    def detectAnnotChange(self):
        return self.main_window.detectAnnotChange


    def annotationTextChanged(self):
        if self.detectAnnotChange:
            self.main_window.setNeedSaving()


    def annotationChanged(self):
        if self.detectAnnotChange:
            self.main_window.setNeedSaving()


    @property
    def currentAnnotation(self):
        return self.main_window.currentAnnotation

    @currentAnnotation.setter
    def currentAnnotation(self, annotation):
        self.main_window.currentAnnotation = annotation


    @pyqtSlot()
    def annotationSelectionChanged(self):
        #self.deleteAnnotationBtn.setEnabled(True)
        self.newAnnotationBtn.setEnabled(True)
        self.duplicateAnnotationBtn.setEnabled(True)
        if not self.currentAnnotation is None:
            self.commentEdt.setText(self.currentAnnotation.comment)
            enableTextWidget(self.commentEdt)
        else:
            self.commentEdt.setText("")
            disableTextWidget(self.commentEdt)            
        
        self.deleteAnnotationBtn.setDisabled(self.currentAnnotation is None)
        self.viewJSONBtn.setDisabled(self.currentAnnotation is None)

    def newAnnotation(self):
        if self.main_window.newAnnotation() :
            self.newAnnotationBtn.setEnabled(False)
            self.duplicateAnnotationBtn.setEnabled(False)
            self.deleteAnnotationBtn.setEnabled(False)
            self.viewJSONBtn.setDisabled(False)
            self.annotationTypesCbo.setEnabled(True)
            self.clearAddAnnotation()
            for widget in self.editAnnotWgt.values():
                widget.newAnnotation()

            if "UNPUBLISHED" in self.main_window.IdTxt.text():
                self.annotationTypesCbo.setEnabled(False)
                self.setCurrentStack(self.annotTypeLst.index("null"))
                self.annotationTypesCbo.setCurrentIndex(self.annotTypeLst.index("null"))
            else:
                self.annotationTypesCbo.setEnabled(True)
            enableTextWidget(self.commentEdt)

    def duplicateAnnotation(self):
        self.main_window.duplicateAnnotation()



    @pyqtSlot(bool)
    def savingNeeded(self, needSaving):
        self.saveAnnotationBtn.setEnabled(needSaving)
        self.updateCurrentAnnotation()



    def updateCurrentAnnotation(self):
        if not self.currentAnnotation is None:
            self.currentAnnotation.comment = self.commentEdt.toPlainText()
            if not self.main_window.username in self.currentAnnotation.users:
                self.currentAnnotation.users.append(self.main_window.username)
            self.editAnnotWgt[self.annotationTypesCbo.currentText()].updateCurrentAnnotation()