Example #1
1
class RangeSelection(QWidget):
    """
    Allow to select a date, a build id, a release number or an arbitrary
    changeset.
    """
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout(self)
        self._create_widgets()
        layout.addWidget(self.stacked)
        layout.addWidget(self.select_combo)
        self.setLayout(layout)

    def _create_widgets(self):
        self.stacked = QStackedWidget()
        self.datew = QDateEdit()
        self.datew.setDisplayFormat("yyyy-MM-dd")
        self.stacked.addWidget(self.datew)
        self.buildidw = QLineEdit()
        self.stacked.addWidget(self.buildidw)
        self.releasew = QComboBox()
        self.releasew.addItems([str(k) for k in sorted(releases())])
        self.stacked.addWidget(self.releasew)
        self.revw = QLineEdit()
        self.stacked.addWidget(self.revw)

        self.select_combo = QComboBox()
        self.select_combo.addItems(['date', 'buildid', 'release', 'changeset'])
        self.select_combo.activated.connect(self.stacked.setCurrentIndex)

    def get_value(self):
        currentw = self.stacked.currentWidget()
        if currentw == self.datew:
            return self.datew.date().toPyDate()
        elif currentw == self.buildidw:
            buildid = unicode(self.buildidw.text())
            try:
                return parse_date(buildid)
            except DateFormatError:
                raise DateFormatError(buildid, "Not a valid build id: `%s`")
        elif currentw == self.releasew:
            return parse_date(
                date_of_release(str(self.releasew.currentText())))
        elif currentw == self.revw:
            return unicode(self.revw.text())
Example #2
0
class ArrayEditor(QDialog):
    """Array Editor Dialog"""
    def __init__(self, parent=None):
        super(ArrayEditor, self).__init__(parent)

    def setup_and_check(self, data, title='', xy=False, readonly=False):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.arraywidget = None
        self.is_record_array = data.dtype.names is not None
        if len(data.shape) > 2:
            self.error(
                self.tr("Arrays with more than 2 dimensions "
                        "are not supported"))
            return False
        if not self.is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('string') \
               and not dtn.startswith('unicode'):
                arr = self.tr("%1 arrays").arg(data.dtype.name)
                self.error(self.tr("%1 are currently not supported").arg(arr))
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(get_icon('arredit.png'))
        title = self.tr("Array editor") + \
                "%s" % (" - "+str(title) if str(title) else "")
        if readonly:
            title += ' (' + self.tr('read only') + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)

        # Stack widget
        self.stack = QStackedWidget(self)
        if self.is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(
                    ArrayEditorWidget(self, data[name], xy, readonly))
        else:
            self.stack.addWidget(ArrayEditorWidget(self, data, xy, readonly))
        self.arraywidget = self.stack.currentWidget()
        self.connect(self.stack, SIGNAL('currentChanged(int)'),
                     self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if self.is_record_array:
            btn_layout.addWidget(QLabel(self.tr("Record array fields:")))
            ra_combo = QComboBox(self)
            self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
                         self.stack.setCurrentIndex)
            names = []
            for name in data.dtype.names:
                field = data.dtype.fields[name]
                text = name
                if len(field) >= 3:
                    title = field[2]
                    if not isinstance(title, basestring):
                        title = repr(title)
                    text += ' - ' + title
                names.append(text)
            ra_combo.addItems(names)
            btn_layout.addWidget(ra_combo)
            btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)

        self.setMinimumSize(400, 300)

        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)

        return True

    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)

    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()
        QDialog.accept(self)

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, self.tr("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
Example #3
0
class EntryView(BaseView):
    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.setMargin(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.setMovable(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)
Example #4
0
class Dialog(KDialog):
    def __init__(self, mainwin):
        KDialog.__init__(self, mainwin)
        self.jobs = []
        self.mainwin = mainwin
        self.setButtons(KDialog.ButtonCode(
            KDialog.Try | KDialog.Help |
            KDialog.Details | KDialog.Reset |
            KDialog.Ok | KDialog.Cancel))
        self.setButtonIcon(KDialog.Try, KIcon("run-lilypond"))
        self.setCaption(i18n("Create blank staff paper"))
        self.setHelp("blankpaper")
        self.setDefaultButton(KDialog.Ok)

        layout = QGridLayout(self.mainWidget())
        self.typeChooser = QComboBox()
        self.stack = QStackedWidget()
        StackFader(self.stack)
        paperSettings = QWidget(self)
        paperSettings.setLayout(QHBoxLayout())
        self.actionChooser = QComboBox(self)
        layout.addWidget(self.typeChooser, 0, 1)
        layout.addWidget(self.stack, 1, 0, 1, 3)
        layout.addWidget(self.actionChooser, 2, 1)
        l = QLabel(i18n("Type:"))
        l.setBuddy(self.typeChooser)
        layout.addWidget(l, 0, 0, Qt.AlignRight)
        l = QLabel(i18n("Action:"))
        l.setBuddy(self.actionChooser)
        layout.addWidget(l, 2, 0, Qt.AlignRight)
        
        # tool tips
        self.typeChooser.setToolTip(i18n(
            "Choose what kind of empty staves you want to create."))
        self.actionChooser.setToolTip(i18n(
            "Choose which action happens when clicking \"Ok\"."))
        self.setButtonToolTip(KDialog.Try, i18n(
            "Preview the empty staff paper."))
        self.setButtonToolTip(KDialog.Details, i18n(
            "Click to see more settings."))
        
        # paper stuff
        paper = QGroupBox(i18n("Paper"))
        paperSettings.layout().addWidget(paper)
        settings = QGroupBox(i18n("Settings"))
        paperSettings.layout().addWidget(settings)
        
        paper.setLayout(QGridLayout())
        
        self.paperSize = QComboBox()
        l = QLabel(i18n("Paper size:"))
        l.setBuddy(self.paperSize)
        paper.layout().addWidget(l, 0, 0, Qt.AlignRight)
        paper.layout().addWidget(self.paperSize, 0, 1)
        self.paperSize.addItem(i18n("Default"))
        self.paperSize.addItems(ly.paperSizes)

        self.staffSize = QSpinBox()
        l = QLabel(i18n("Staff Size:"))
        l.setBuddy(self.staffSize)
        paper.layout().addWidget(l, 1, 0, Qt.AlignRight)
        paper.layout().addWidget(self.staffSize, 1, 1)
        self.staffSize.setRange(8, 40)
        
        self.pageCount = QSpinBox()
        l = QLabel(i18n("Page count:"))
        l.setBuddy(self.pageCount)
        paper.layout().addWidget(l, 2, 0, Qt.AlignRight)
        paper.layout().addWidget(self.pageCount, 2, 1)
        self.pageCount.setRange(1, 1000)
        
        self.removeTagline = QCheckBox(i18n("Remove default tagline"))
        paper.layout().addWidget(self.removeTagline, 3, 0, 1, 2)
        
        settings.setLayout(QGridLayout())
        
        self.barLines = QCheckBox(i18n("Print Bar Lines"))
        self.barsPerLine = QSpinBox()
        l = QLabel(i18n("Bars per line:"))
        l.setBuddy(self.barsPerLine)
        settings.layout().addWidget(self.barLines, 0, 0, 1, 2)
        settings.layout().addWidget(l, 1, 0, Qt.AlignRight)
        settings.layout().addWidget(self.barsPerLine, 1, 1)
        self.barsPerLine.setRange(1, 20)
        
        self.pageNumbers = QCheckBox(i18n("Print Page Numbers"))
        self.pageNumStart = QSpinBox()
        l = QLabel(i18n("Start with:"))
        l.setBuddy(self.pageNumStart)
        settings.layout().addWidget(self.pageNumbers, 2, 0, 1, 2)
        settings.layout().addWidget(l, 3, 0, Qt.AlignRight)
        settings.layout().addWidget(self.pageNumStart, 3, 1)
        self.barLines.toggled.connect(self.barsPerLine.setEnabled)
        self.pageNumbers.toggled.connect(self.pageNumStart.setEnabled)
        
        # types
        self.typeWidgets = [
            SingleStaff(self),
            PianoStaff(self),
            OrganStaff(self),
            ChoirStaff(self),
            CustomStaff(self),
            ]
        for widget in self.typeWidgets:
            self.stack.addWidget(widget)
            self.typeChooser.addItem(widget.name())
        self.typeChooser.currentIndexChanged.connect(lambda index:
            self.stack.setCurrentWidget(self.typeWidgets[index]))

        self.actors = [
            PrintPDF,
            SavePDF,
            OpenPDF,
            CopyToEditor,
            ]
        for actor in self.actors:
            self.actionChooser.addItem(actor.name())
        
        self.setDetailsWidget(paperSettings)
        # cleanup on exit
        mainwin.aboutToClose.connect(self.cleanup)
        # buttons
        self.resetClicked.connect(self.default)
        self.tryClicked.connect(self.showPreview)
        self.setInitialSize(QSize(400, 240))
        self.default()
        self.loadSettings()
    
    def done(self, r):
        self.saveSettings()
        KDialog.done(self, r)
        if r:
            self.actors[self.actionChooser.currentIndex()](self)

    def default(self):
        """ Set everything to default """
        self.paperSize.setCurrentIndex(0)
        self.staffSize.setValue(22)
        self.pageCount.setValue(1)
        self.removeTagline.setChecked(False)
        self.barLines.setChecked(False)
        self.barsPerLine.setValue(4)
        self.barsPerLine.setEnabled(False)
        self.pageNumbers.setChecked(False)
        self.pageNumStart.setValue(1)
        self.pageNumStart.setEnabled(False)
        self.typeChooser.setCurrentIndex(0)
        self.actionChooser.setCurrentIndex(0)
        for widget in self.typeWidgets:
            widget.default()

    def loadSettings(self):
        conf = config()
        self.removeTagline.setChecked(conf.readEntry("remove tagline", False))
        action = conf.readEntry("action", "PrintPDF")
        for index, actor in enumerate(self.actors):
            if actor.__name__ == action:
                self.actionChooser.setCurrentIndex(index)
    
    def saveSettings(self):
        conf = config()
        conf.writeEntry("remove tagline", self.removeTagline.isChecked())
        action = self.actors[self.actionChooser.currentIndex()].__name__
        conf.writeEntry("action", action)
    
    def showPreview(self):
        self.previewDialog().showPreview(self.ly())

    @cacheresult
    def previewDialog(self):
        return PreviewDialog(self)

    def ly(self):
        """
        Return the LilyPond document to print the empty staff paper.
        """
        staff = self.stack.currentWidget()
        output = []
        version = lilyPondVersion()
        if version:
            output.append('\\version "{0}"\n'.format(version))
        output.append('#(set-global-staff-size {0})\n'.format(self.staffSize.value()))
        # paper section
        output.append('\\paper {')
        if self.paperSize.currentIndex() > 0:
            output.append('#(set-paper-size "{0}")'.format(ly.paperSizes[self.paperSize.currentIndex()-1]))
        if self.pageNumbers.isChecked():
            output.append('top-margin = 10\\mm')
            output.append('first-page-number = #{0}'.format(self.pageNumStart.value()))
            output.append('oddHeaderMarkup = \\markup \\fill-line {')
            output.append('\\strut')
            output.append("\\fromproperty #'page:page-number-string")
            output.append('}')
        else:
            output.append('top-margin = 16\\mm')
            output.append('oddHeaderMarkup = ##f')
        output.append('evenHeaderMarkup = ##f')
        if self.removeTagline.isChecked():
            output.append('bottom-margin = 16\\mm')
            output.append('oddFooterMarkup = ##f')
        else:
            output.append('bottom-margin = 10\\mm')
            output.append('oddFooterMarkup = \\markup \\abs-fontsize #6 \\fill-line {')
            tagline = config().readEntry("tagline",
                '\\with-url #"http://www.frescobaldi.org/" FRESCOBALDI.ORG')
            output.append('\\sans {{ {0} }}'.format(tagline))
            output.append('\\strut')
            output.append('}')
        output.append('evenFooterMarkup = ##f')
        output.append('ragged-last-bottom = ##f')
        output.append('ragged-right = ##f')
        output.append('}\n')
        # music expression
        output.append('music = \\repeat unfold {0} {{ % pages'.format(self.pageCount.value()))
        output.append('\\repeat unfold {0} {{ % systems'.format(staff.systemCount()))
        output.append('\\repeat unfold {0} {{ % bars'.format(
            self.barLines.isChecked() and self.barsPerLine.value() or 1))
        output.extend(('r1', '\\noBreak', '}', '\\break', '\\noPageBreak', '}', '\\pageBreak', '}\n'))

        # get the layout
        layout = LayoutContexts()
        layout.add("Score", '\\remove "Bar_number_engraver"')
        layout.add("Voice", "\\override Rest #'stencil = ##f")
        music = staff.music(layout)
        layout.addToStaffContexts('\\remove "Time_signature_engraver"')
        if not self.barLines.isChecked():
            layout.disableBarLines()
        # write it out
        output.append('\\layout {\nindent = #0')
        output.extend(layout.ly())
        output.append('}\n')
        
        # score
        output.append('\\score {')
        output.extend(music)
        output.append('}\n')
        return ly.indent.indent('\n'.join(output))

    def cleanup(self):
        for job in self.jobs[:]: # copy
            job.cleanup()
class E4SideBar(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)
        """
        QWidget.__init__(self, 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.trUtf8("Deselect to activate automatic collapsing"))
        self.barLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.barLayout.setMargin(0)
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setMargin(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.connect(self.__delayTimer, SIGNAL("timeout()"), 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 = E4SideBar.North
        if orientation is None:
            orientation = E4SideBar.North
        self.setOrientation(orientation)
        
        self.connect(self.__tabBar, SIGNAL("currentChanged(int)"), 
                     self.__stackedWidget, SLOT("setCurrentIndex(int)"))
        self.connect(e4App(), SIGNAL("focusChanged(QWidget*, QWidget*)"), 
                     self.__appFocusChanged)
        self.connect(self.__autoHideButton, SIGNAL("toggled(bool)"), 
                     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.connect(self.splitter, SIGNAL("splitterMoved(int, int)"), 
                     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 [E4SideBar.North, E4SideBar.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 [E4SideBar.North, E4SideBar.South]:
            self.setFixedHeight(self.__tabBar.minimumSizeHint().height())
        else:
            self.setFixedWidth(self.__tabBar.minimumSizeHint().width())
        
        self.__actionMethod = None
    
    def expand(self):
        """
        Private method to record a expand request.
        """
        self.__delayTimer.stop()
        self.__actionMethod = self.__expandIt
        self.__delayTimer.start()
    
    def __expandIt(self):
        """
        Public method to expand the sidebar.
        """
        self.__minimized = False
        self.__stackedWidget.show()
        self.resize(self.__bigSize)
        if self.__orientation in [E4SideBar.North, E4SideBar.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):
        """
        Protected 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 and not self.__stackedWidget.isHidden():
                if evt.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 labeltext of the tab
            (QIcon, string or QString)
        @param label the labeltext of the tab (string or QString) (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 [E4SideBar.North, E4SideBar.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 or QString)
        @param label the labeltext of the tab (string or QString) (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 [E4SideBar.North, E4SideBar.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 [E4SideBar.North, E4SideBar.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 == E4SideBar.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 == E4SideBar.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 == E4SideBar.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 == E4SideBar.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 (QString)
        """
        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 (QString)
        """
        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 (QString)
        """
        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 tooltip text text to set (QString)
        """
        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 (QString)
        """
        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 WhatsThis text text to set (QString)
        """
        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 [E4SideBar.North, E4SideBar.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.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 [E4SideBar.North, E4SideBar.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.readUInt16()  # version
        minimized = stream.readBool()
        
        if 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.
        """
        self.disconnect(e4App(), SIGNAL("focusChanged(QWidget*, QWidget*)"), 
                        self.__appFocusChanged)
Example #6
0
class ConfigDialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.contents_widget = QListWidget()
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setMinimumWidth(120)
        self.contents_widget.setMaximumWidth(120)
        self.contents_widget.setSpacing(1)

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply
                                | QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"),
                     self.button_clicked)

        self.pages_widget = QStackedWidget()
        self.connect(self.pages_widget, SIGNAL("currentChanged(int)"),
                     self.current_page_changed)

        self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"),
                     self.pages_widget.setCurrentIndex)
        self.contents_widget.setCurrentRow(0)

        hlayout = QHBoxLayout()
        hlayout.addWidget(self.contents_widget)
        hlayout.addWidget(self.pages_widget)
        hlayout.setStretch(1, 1)

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

        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

        self.setWindowTitle("Preferences")
        self.setWindowIcon(get_icon("configure.png"))

    def get_current_index(self):
        """Return current page index"""
        return self.contents_widget.currentRow()

    def set_current_index(self, index):
        """Set current page index"""
        self.contents_widget.setCurrentRow(index)

    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.pages_widget.count()):
            configpage = self.pages_widget.widget(index)
            if not configpage.is_valid():
                return
            configpage.apply_changes()
        QDialog.accept(self)

    def button_clicked(self, button):
        if button is self.apply_btn:
            # Apply button was clicked
            configpage = self.pages_widget.currentWidget()
            if not configpage.is_valid():
                return
            configpage.apply_changes()

    def current_page_changed(self, index):
        widget = self.pages_widget.widget(index)
        self.apply_btn.setVisible(widget.apply_callback is not None)
        self.apply_btn.setEnabled(widget.is_modified)

    def add_page(self, widget):
        self.connect(self, SIGNAL('check_settings()'), widget.check_settings)
        self.connect(widget,
                     SIGNAL('show_this_page()'),
                     lambda row=self.contents_widget.count(): self.
                     contents_widget.setCurrentRow(row))
        self.connect(widget, SIGNAL("apply_button_enabled(bool)"),
                     self.apply_btn.setEnabled)
        self.pages_widget.addWidget(widget)
        item = QListWidgetItem(self.contents_widget)
        item.setIcon(widget.get_icon())
        item.setText(widget.get_name())
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        item.setSizeHint(QSize(0, 25))

    def check_all_settings(self):
        """This method is called to check all configuration page settings
        after configuration dialog has been shown"""
        self.emit(SIGNAL('check_settings()'))
class EditorContainer(QWidget):

    # Señales
    closedFile = pyqtSignal(int)
    savedFile = pyqtSignal('QString')
    cursorPosition = pyqtSignal(int, int, int)
    updateSymbols = pyqtSignal('PyQt_PyObject')
    fileChanged = pyqtSignal('QString')
    openedFile = pyqtSignal('QString')

    def __init__(self, edis=None):
        QWidget.__init__(self, edis)
        self.setAcceptDrops(True)
        self.box = QVBoxLayout(self)
        self.box.setContentsMargins(0, 0, 0, 0)
        self.box.setSpacing(0)

        # Stacked
        self.stack = QStackedWidget()
        self.box.addWidget(self.stack)

        # Replace widget
        #FIXME: mover esto
        self._replace_widget = replace_widget.ReplaceWidget()
        self._replace_widget.hide()
        self.box.addWidget(self._replace_widget)

        # Editor widget
        self.editor_widget = editor_widget.EditorWidget()

        # Conexiones
        self.connect(self.editor_widget, SIGNAL("saveCurrentFile()"),
                     self.save_file)
        self.connect(self.editor_widget, SIGNAL("fileClosed(int)"),
                     self._file_closed)
        self.connect(self.editor_widget, SIGNAL("recentFile(QStringList)"),
                     self.update_recents_files)
        self.connect(self.editor_widget, SIGNAL("allFilesClosed()"),
                     self.add_start_page)
        self.connect(self.editor_widget, SIGNAL("currentWidgetChanged(int)"),
                     self.change_widget)

        Edis.load_component("principal", self)

    def update_recents_files(self, recents_files):
        """ Actualiza el submenú de archivos recientes """

        menu = Edis.get_component("menu_recent_file")
        self.connect(menu, SIGNAL("triggered(QAction*)"),
                     self._open_recent_file)
        menu.clear()
        for _file in recents_files:
            menu.addAction(_file)

    def _open_recent_file(self, accion):
        """ Abre el archivo desde el menú """

        self.open_file(accion.text())

    def get_recents_files(self):
        """ Devuelve una lista con los archivos recientes en el menú """

        menu = Edis.get_component('menu_recent_file')
        actions = menu.actions()
        recents_files = []
        for filename in actions:
            recents_files.append(filename.text())
        return recents_files

    def _file_closed(self, index):
        self.closedFile.emit(index)

    def _file_modified(self, value):
        self.editor_widget.editor_modified(value)

    def _file_saved(self, filename):
        self.editor_widget.editor_modified(False)
        self.emit(SIGNAL("updateSymbols(QString)"), filename)

    def change_widget(self, index):
        weditor = self.get_active_editor()
        self.editor_widget.combo.combo_file.setCurrentIndex(index)
        if weditor is not None and not weditor.obj_file.is_new:
            self.emit(SIGNAL("updateSymbols(QString)"), weditor.filename)
            self.emit(SIGNAL("fileChanged(QString)"), weditor.filename)
            weditor.setFocus()

    def create_editor(self, obj_file=None, filename=""):
        if obj_file is None:
            obj_file = object_file.EdisFile(filename)
        self.stack.addWidget(self.editor_widget)
        # Quito la página de inicio, si está
        _start_page = self.stack.widget(0)
        if isinstance(_start_page, start_page.StartPage):
            self.remove_widget(_start_page)
            # Detengo el tiimer
            _start_page.timer.stop()
        weditor = editor.Editor(obj_file)
        self.editor_widget.add_widget(weditor)
        self.editor_widget.add_item_combo(obj_file.filename)
        lateral = Edis.get_component("tab_container")
        if not lateral.isVisible():
            lateral.show()

        # Conexiones
        self.connect(obj_file, SIGNAL("fileChanged(PyQt_PyObject)"),
                     self._file_changed)
        self.connect(weditor, SIGNAL("cursorPositionChanged(int, int)"),
                     self.update_cursor)
        self.connect(weditor, SIGNAL("modificationChanged(bool)"),
                     self._file_modified)
        self.connect(weditor, SIGNAL("fileSaved(QString)"),
                     self._file_saved)
        self.connect(weditor, SIGNAL("linesChanged(int)"),
                     self.editor_widget.combo.move_to_symbol)
        self.connect(weditor, SIGNAL("dropEvent(PyQt_PyObject)"),
                     self._drop_editor)
        self.emit(SIGNAL("fileChanged(QString)"), obj_file.filename)

        weditor.setFocus()

        return weditor

    def _file_changed(self, obj_file):
        filename = obj_file.filename
        flags = QMessageBox.Yes
        flags |= QMessageBox.No
        result = QMessageBox.information(self, self.tr("Monitoreo de Archivo"),
                                         self.tr("El archivo <b>{0}</b> fué "
                                         "modificado fuera de Edis. "
                                         "<br><br> Quieres recar"
                                         "garlo?".format(filename)), flags)
        if result == QMessageBox.No:
            return
        self.reload_file(obj_file)

    def reload_file(self, obj_file=None):
        weditor = self.get_active_editor()
        if weditor is None:
            return
        if obj_file is None:
            obj_file = weditor.obj_file
        content = obj_file.read()
        if weditor.is_modified:
            result = QMessageBox.information(self, self.tr(
                "Archivo no guardado!"),
                self.tr("Seguro que quieres recargar el archivo <b>{0}</b>?"
                        "<br><br>"
                        "Se perderán los cambios no guardados.").format(
                            obj_file.filename),
                QMessageBox.Cancel | QMessageBox.Yes)
            if result == QMessageBox.Cancel:
                return
        weditor.setText(content)
        weditor.markerDeleteAll()
        weditor.setModified(False)

    def open_file(self, filename="", cursor_position=None):
        filter_files = "Archivos C(*.cpp *.c);;ASM(*.s);;HEADERS(*.h);;(*.*)"
        if not filename:
            working_directory = os.path.expanduser("~")
            weditor = self.get_active_editor()
            if weditor and weditor.filename:
                working_directory = self._last_folder(weditor.filename)
            filenames = QFileDialog.getOpenFileNames(self,
                                                     self.tr("Abrir Archivo"),
                                                     working_directory,
                                                     filter_files)
        else:
            filenames = [filename]
        try:
            for _file in filenames:
                if not self._is_open(_file):
                    #self.editor_widget.not_open = False
                    # Creo el objeto Edis File
                    obj_file = object_file.EdisFile(_file)
                    content = obj_file.read()
                    weditor = self.create_editor(obj_file, _file)
                    weditor.setText(content)
                    # Cuando se setea el contenido en el editor
                    # se emite la señal textChanged() por lo tanto se agrega
                    # el marker, entonces se procede a borrarlo
                    weditor.markerDelete(0, 3)
                    # FIXME: Cursor position not found
                    #if cursor_position is not None:
                        #line, row = cursor_position
                        #weditor.setCursorPosition(line, row)
                    weditor.setModified(False)
                    obj_file.run_system_watcher()
                else:
                    # Se cambia el índice del stacked
                    # para mostrar el archivo que ya fué abierto
                    for index in range(self.editor_widget.count()):
                        editor = self.editor_widget.widget(index)
                        if editor.filename == _file:
                            self.change_widget(index)

                self.emit(SIGNAL("fileChanged(QString)"), _file)
                self.emit(SIGNAL("openedFile(QString)"), _file)
                self.emit(SIGNAL("updateSymbols(QString)"), _file)
        except EdisIOError as error:
            ERROR('Error al intentar abrir archivo: %s', error)
            QMessageBox.critical(self, self.tr('No se pudo abrir el archivo'),
                                 str(error))
        #self.editor_widget.not_open = True

    def _last_folder(self, path):
        """ Devuelve la última carpeta a la que se accedió """

        return QFileInfo(path).absolutePath()

    def _is_open(self, archivo):
        """
        Retorna True si un archivo ya esta abierto,
        False en caso contrario

        """

        for index in range(self.editor_widget.count()):
            widget = self.editor_widget.widget(index)
            if widget.filename == archivo:
                return True
        return False

    def add_widget(self, widget):
        """ Agrega @widget al stacked """

        self.editor_widget.add_widget(widget)

    def add_start_page(self):
        """ Agrega la página de inicio al stack """

        if settings.get_setting('general/show-start-page'):
            _start_page = start_page.StartPage()
            self.stack.insertWidget(0, _start_page)
            self.stack.setCurrentIndex(0)
        else:
            self.editor_widget.combo.setVisible(False)

    def remove_widget(self, widget):
        """ Elimina el @widget del stacked """

        self.stack.removeWidget(widget)

    def current_widget(self):
        """ Widget actual """

        return self.editor_widget.current_widget()

    def current_index(self):
        return self.editor_widget.current_index()

    def get_active_editor(self):
        """ Devuelve el Editor si el widget actual es una instancia de él,
        de lo contrario devuelve None. """

        widget = self.current_widget()
        if isinstance(widget, editor.Editor):
            return widget
        return None

    def close_file(self):
        self.editor_widget.close_file()

    def close_file_from_project(self, filename):
        #FIXME: revisar
        for index in range(self.editor_widget.count()):
            widget = self.editor_widget.widget(index)
            if widget.filename == filename:
                editor, i = widget, index
        self.editor_widget.close_file_project(editor, i)

    def close_all(self):
        self.editor_widget.close_all()

    def show_selector(self):
        if self.get_active_editor() is not None:
            selector = file_selector.FileSelector(self)
            selector.show()

    def save_file(self, weditor=None):
        if weditor is None:
            weditor = self.get_active_editor()
            if weditor is None:
                return
        if weditor.obj_file.is_new:
            return self.save_file_as(weditor)
        source_code = weditor.text()
        weditor.obj_file.write(source_code)
        weditor.saved()
        # System watcher
        weditor.obj_file.run_system_watcher()
        self.savedFile.emit(weditor.filename)
        return weditor.filename

    def save_file_as(self, weditor=None):
        if weditor is None:
            weditor = self.get_active_editor()
            if weditor is None:
                return
        working_directory = os.path.expanduser("~")
        filename = QFileDialog.getSaveFileName(self, self.tr("Guardar Archivo"),
                                               working_directory)
        if not filename:
            return False
        content = weditor.text()
        weditor.obj_file.write(content, filename)
        weditor.saved()
        self.fileChanged.emit(weditor.filename)
        self.savedFile.emit(weditor.filename)
        return filename

    def save_selected(self, filename):
        for index in range(self.editor_widget.count()):
            if self.editor_widget.widget(index).filename == filename:
                self.save_file(self.editor_widget.widget(index))

    def files_not_saved(self):
        return self.editor_widget.files_not_saved()

    def check_files_not_saved(self):
        return self.editor_widget.check_files_not_saved()

    def find(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            dialog = find_popup.PopupBusqueda(self.get_active_editor())
            dialog.show()

    def find_and_replace(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            if self._replace_widget.isVisible():
                self._replace_widget.hide()
                weditor.setFocus()
            else:
                self._replace_widget.show()

    def action_undo(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.undo()

    def action_redo(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.redo()

    def action_cut(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.cut()

    def action_copy(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.copy()

    def action_paste(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.paste()

    def show_tabs_and_spaces(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            tabs_spaces = settings.get_setting('editor/show-tabs-spaces')
            settings.set_setting('editor/show-tabs-spaces', not tabs_spaces)
            weditor.update_options()

    def show_indentation_guides(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            guides = settings.get_setting('editor/show-guides')
            settings.set_setting('editor/show-guides', not guides)
            weditor.update_options()

    def delete_editor_markers(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.markerDeleteAll()

    def action_zoom_in(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.zoom_in()

    def action_zoom_out(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.zoom_out()

    def action_normal_size(self):
        """ Carga el tamaño por default de la fuente """

        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.zoomTo(0)

    def action_select_all(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.selectAll()

    def opened_files(self):
        return self.editor_widget.opened_files()

    def opened_files_for_selector(self):
        self.index_file_selector = 0
        files = []
        for index in range(self.editor_widget.count()):
            weditor = self.editor_widget.widget(index)
            path = weditor.filename
            if not path:
                path = weditor.display + ' (%s)' % self.index_file_selector
                self.index_file_selector += 1
            files.append(path)
        return files

    def get_open_projects(self):
        tree_projects = Edis.get_lateral("tree_projects")
        return tree_projects.get_open_projects()

    def file_properties(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            dialog = file_properties.FileProperty(weditor, self)
            dialog.show()

    def update_cursor(self, line, row):
        weditor = self.get_active_editor()
        lines = weditor.lines()
        self.editor_widget.combo.update_cursor_position(
            line + 1, row + 1, lines)
        self.cursorPosition.emit(line + 1, row + 1, lines)

    def build_source_code(self):
        output = Edis.get_component("output")
        project = Edis.get_lateral("tree_projects")
        weditor = self.get_active_editor()
        if weditor is not None:
            filename = self.save_file()
            if project.sources:
                output.build((filename, project.sources))
            else:
                if filename:
                    output.build((weditor.filename, []))

    def run_binary(self):
        """ Ejecuta el programa objeto """

        output = Edis.get_component("output")
        output.run()

    def build_and_run(self):
        output = Edis.get_component("output")
        weditor = self.get_active_editor()
        if weditor is not None:
            self.save_file()
            output.build_and_run(weditor.filename)

    def clean_construction(self):
        output = Edis.get_component("output")
        output.clean()

    def stop_program(self):
        output = Edis.get_component("output")
        output.stop()

    def action_comment(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.comment()

    def action_uncomment(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.uncomment()

    def action_indent(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.indent_more()

    def action_unindent(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.indent_less()

    def action_to_lowercase(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.to_lowercase()

    def action_to_uppercase(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.to_uppercase()

    def action_to_title(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.to_title()

    def action_duplicate_line(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.duplicate_line()

    def action_delete_line(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.delete_line()

    def action_move_down(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.move_down()

    def action_move_up(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.move_up()

    def reemplazar_tabs_por_espacios(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.reemplazar_tabs_por_espacios()

    def go_to_line(self, line):
        weditor = self.get_active_editor()
        if weditor is not None:
            weditor.setCursorPosition(line, 0)

    def show_go_to_line(self):
        weditor = self.get_active_editor()
        if weditor is not None:
            dialog = goto_line_widget.GoToLineDialog(weditor)
            dialog.show()

    def add_symbols_combo(self, symbols):
        self.editor_widget.add_symbols(symbols)

    def dragEnterEvent(self, event):
        data = event.mimeData()
        if data.hasText():
            # Se acepta el evento de arrastrado
            event.accept()

    def dropEvent(self, event):
        self._drop_event(event)

    def _drop_editor(self, event):
        self._drop_event(event)

    def _drop_event(self, event):
        data = event.mimeData()
        filename = data.urls()[0].toLocalFile()
        self.open_file(filename)

    def show_settings(self):
        preferences_widget = Edis.get_component("preferences")
        current_widget = self.stack.currentWidget()
        if isinstance(current_widget, preferences_widget.__class__):
            return
        self.connect(preferences_widget,
                     SIGNAL("configurationsClose(PyQt_PyObject)"),
                     lambda widget: self.remove_widget(widget))
        index = self.stack.addWidget(preferences_widget)
        self.stack.setCurrentIndex(index)

    def open_project(self, filename='', edis_project=True):
        if edis_project:
            if not filename:
                filename = QFileDialog.getOpenFileName(self,
                                                       self.tr("Cargar "
                                                       "Proyecto"),
                                                       paths.PROJECT_DIR,
                                                       "Archivo Edis(*.epf)")
                if not filename:
                    return
                project_file = json.load(open(filename))
                project_path = project_file.get('path', '')
            else:
                project_path = os.path.dirname(filename)
        else:
            result = QFileDialog.getExistingDirectory(self,
                                                      self.tr("Selecciona "
                                                      "la carpeta"))
            if not result:
                return
            project_path = result
        project_structure = {}
        filter_files = ['.c', '.h']
        for parent, dirs, files in os.walk(project_path):
            files = [fi for fi in files
                     if os.path.splitext(fi)[-1] in filter_files]
            project_structure[parent] = (files, dirs)
        self.emit(SIGNAL("projectOpened(PyQt_PyObject)"),
                  (project_structure, project_path, edis_project, filename))

    def open_directory(self):
        self.open_project(edis_project=False)

    def create_new_project(self):
        project_creator = new_project.NewProjectDialog(self)
        self.connect(project_creator, SIGNAL("projectReady(PyQt_PyObject)"),
                     self._update_data)
        project_creator.show()

    def _update_data(self, data):
        self.emit(SIGNAL("projectReady(PyQt_PyObject)"), data)

    def opened_projects(self):
        pass

    def code_pasting(self):
        if self.get_active_editor() is not None:
            code = self.get_active_editor().text()
            code_pasting = code_pasting_dialog.CodePastingDialog(self, code)
            code_pasting.exec_()

    def show_snake(self):
        from src.ui.widgets.pyborita import pyborita_widget
        w = pyborita_widget.PyboritaWidget(self)
        toolbar = Edis.get_component("toolbar")
        lateral = Edis.get_component("tab_container")
        status = Edis.get_component("status_bar")
        output = Edis.get_component("output")
        widgets = [toolbar, status, lateral, output]
        for widget in widgets:
            widget.hide()
        self.stack.insertWidget(0, w)
        self.stack.setCurrentIndex(0)
Example #8
0
class ConfigDialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.contents_widget = QListWidget()
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setMinimumWidth(120)
        self.contents_widget.setMaximumWidth(120)
        self.contents_widget.setSpacing(1)

        bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Apply
                                     |QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"),
                     self.button_clicked)

        self.pages_widget = QStackedWidget()
        self.connect(self.pages_widget, SIGNAL("currentChanged(int)"),
                     self.current_page_changed)

        self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"),
                     self.pages_widget.setCurrentIndex)
        self.contents_widget.setCurrentRow(0)

        hlayout = QHBoxLayout()
        hlayout.addWidget(self.contents_widget)
        hlayout.addWidget(self.pages_widget)
        hlayout.setStretch(1,1)

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

        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addLayout(btnlayout)

        self.setLayout(vlayout)

        self.setWindowTitle("Preferences")
        self.setWindowIcon(get_icon("configure.png"))
        
    def get_current_index(self):
        """Return current page index"""
        return self.contents_widget.currentRow()
        
    def set_current_index(self, index):
        """Set current page index"""
        self.contents_widget.setCurrentRow(index)
        
    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.pages_widget.count()):
            configpage = self.pages_widget.widget(index)
            if not configpage.is_valid():
                return
            configpage.apply_changes()
        QDialog.accept(self)
        
    def button_clicked(self, button):
        if button is self.apply_btn:
            # Apply button was clicked
            configpage = self.pages_widget.currentWidget()
            if not configpage.is_valid():
                return
            configpage.apply_changes()
            
    def current_page_changed(self, index):
        widget = self.pages_widget.widget(index)
        self.apply_btn.setVisible(widget.apply_callback is not None)
        self.apply_btn.setEnabled(widget.is_modified)
        
    def add_page(self, widget):
        self.connect(self, SIGNAL('check_settings()'), widget.check_settings)
        self.connect(widget, SIGNAL('show_this_page()'),
                     lambda row=self.contents_widget.count():
                     self.contents_widget.setCurrentRow(row))
        self.connect(widget, SIGNAL("apply_button_enabled(bool)"),
                     self.apply_btn.setEnabled)
        self.pages_widget.addWidget(widget)
        item = QListWidgetItem(self.contents_widget)
        item.setIcon(widget.get_icon())
        item.setText(widget.get_name())
        item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        item.setSizeHint(QSize(0, 25))
        
    def check_all_settings(self):
        """This method is called to check all configuration page settings
        after configuration dialog has been shown"""
        self.emit(SIGNAL('check_settings()'))
Example #9
0
class EditorWidget(QWidget):

    # Señales
    allFilesClosed = pyqtSignal()

    def __init__(self):
        super(EditorWidget, self).__init__()
        self._recents_files = []

        box = QVBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)
        box.setSpacing(0)

        # Combo container
        self.combo = ComboContainer(self)
        box.addWidget(self.combo)

        # Stacked
        self.stack = QStackedWidget()
        box.addWidget(self.stack)

        self.connect(self.combo.combo_file,
                     SIGNAL("currentIndexChanged(int)"), self.change_item)

    def add_widget(self, widget):
        index = self.stack.addWidget(widget)
        if not self.combo.isVisible():
            self.combo.setVisible(True)
        self.stack.setCurrentIndex(index)

    def add_item_combo(self, text):
        self.combo.combo_file.addItem(text)
        self.combo.combo_file.setCurrentIndex(
            self.combo.combo_file.count() - 1)

    def remove_item_combo(self, index):
        self.combo.combo_file.removeItem(index)

    def change_item(self, index):
        self.stack.setCurrentIndex(index)
        self.emit(SIGNAL("currentWidgetChanged(int)"), index)

    def current_widget(self):
        return self.stack.currentWidget()

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

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

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

    def close_file(self):
        self.remove_widget(self.current_widget(), self.current_index())

    def close_file_project(self, widget, index):
        #FIXME: unir con close file
        self.remove_widget(widget, index)

    def close_all(self):
        for index in range(self.count()):
            self.remove_widget(self.current_widget(), 0)

    def editor_modified(self, value):
        weditor = self.current_widget()
        index = self.current_index()
        self.combo.set_modified(weditor, index, value)

    def _add_to_recent(self, filename):
        if filename == 'Untitled':
            return
        if filename not in self._recents_files:
            self._recents_files.append(filename)
            self.emit(SIGNAL("recentFile(QStringList)"), self._recents_files)

    def check_files_not_saved(self):
        value = False
        for index in range(self.count()):
            weditor = self.widget(index)
            value = value or weditor.is_modified
        return value

    def files_not_saved(self):
        files = []
        for index in range(self.count()):
            weditor = self.widget(index)
            if weditor.is_modified:
                files.append(weditor.filename)
        return files

    def opened_files(self):
        files = []
        for index in range(self.count()):
            weditor = self.widget(index)
            path = weditor.filename
            if path == 'Untitled':
                continue
            files.append(path)
        return files

    def remove_widget(self, widget, index):
        if not isinstance(widget, editor.Editor):
            return
        if index != -1:
            self.stack.setCurrentIndex(index)

            flags = QMessageBox.Yes
            flags |= QMessageBox.No
            flags |= QMessageBox.Cancel

            result = QMessageBox.No
            if widget.is_modified:
                result = QMessageBox.question(self, self.tr(
                    "Archivo no guardado!"),
                    self.tr("El archivo <b>{0}</b> "
                            "tiene cambios sin guardar. "
                            "Quieres guardarlos?").format(widget.filename),
                    QMessageBox.Yes, QMessageBox.No, QMessageBox.Cancel)
                if result == QMessageBox.Cancel:
                    return
                elif result == QMessageBox.Yes:
                    self.emit(SIGNAL("saveCurrentFile()"))
            self._add_to_recent(widget.filename)
            self.stack.removeWidget(widget)
            self.emit(SIGNAL("fileClosed(int)"), index)
            self.remove_item_combo(index)
            widget.obj_file.stop_system_watcher()
            if self.current_widget() is not None:
                self.current_widget().setFocus()
            else:
                self.allFilesClosed.emit()

    def add_symbols(self, symbols):
        self.combo.add_symbols_combo(symbols)
Example #10
0
class ConfigDialog(QDialog):
    """Spyder configuration ('Preferences') dialog box"""
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.contents_widget = QListWidget()
        self.contents_widget.setMovement(QListView.Static)
        self.contents_widget.setSpacing(1)

        bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Apply
                                |QDialogButtonBox.Cancel)
        self.apply_btn = bbox.button(QDialogButtonBox.Apply)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"),
                     self.button_clicked)

        self.pages_widget = QStackedWidget()
        self.connect(self.pages_widget, SIGNAL("currentChanged(int)"),
                     self.current_page_changed)

        self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"),
                     self.pages_widget.setCurrentIndex)
        self.contents_widget.setCurrentRow(0)

        hsplitter = QSplitter()
        hsplitter.addWidget(self.contents_widget)
        hsplitter.addWidget(self.pages_widget)

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

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

        self.setLayout(vlayout)

        self.setWindowTitle(_("Preferences"))
        self.setWindowIcon(get_icon("configure.png"))
        
    def get_current_index(self):
        """Return current page index"""
        return self.contents_widget.currentRow()
        
    def set_current_index(self, index):
        """Set current page index"""
        self.contents_widget.setCurrentRow(index)
        
    def get_page(self, index=None):
        """Return page widget"""
        if index is None:
            widget = self.pages_widget.currentWidget()
        else:
            widget = self.pages_widget.widget(index)
        return widget.widget()
        
    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.pages_widget.count()):
            configpage = self.get_page(index)
            if not configpage.is_valid():
                return
            configpage.apply_changes()
        QDialog.accept(self)
        
    def button_clicked(self, button):
        if button is self.apply_btn:
            # Apply button was clicked
            configpage = self.get_page()
            if not configpage.is_valid():
                return
            configpage.apply_changes()
            
    def current_page_changed(self, index):
        widget = self.get_page(index)
        self.apply_btn.setVisible(widget.apply_callback is not None)
        self.apply_btn.setEnabled(widget.is_modified)
        
    def add_page(self, widget):
        self.connect(self, SIGNAL('check_settings()'), widget.check_settings)
        self.connect(widget, SIGNAL('show_this_page()'),
                     lambda row=self.contents_widget.count():
                     self.contents_widget.setCurrentRow(row))
        self.connect(widget, SIGNAL("apply_button_enabled(bool)"),
                     self.apply_btn.setEnabled)
        scrollarea = QScrollArea(self)
        scrollarea.setWidgetResizable(True)
        scrollarea.setWidget(widget)
        self.pages_widget.addWidget(scrollarea)
        item = QListWidgetItem(self.contents_widget)
        item.setIcon(widget.get_icon())
        item.setText(widget.get_name())
        item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        item.setSizeHint(QSize(0, 25))
        
    def check_all_settings(self):
        """This method is called to check all configuration page settings
        after configuration dialog has been shown"""
        self.emit(SIGNAL('check_settings()'))
    
    def resizeEvent(self, event):
        """
        Reimplement Qt method to be able to save the widget's size from the
        main application
        """
        QDialog.resizeEvent(self, event)
        self.emit(SIGNAL("size_change(QSize)"), self.size())
Example #11
0
class ArrayEditor(QDialog):
    """Array Editor Dialog"""

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

        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.data = None
        self.arraywidget = None
        self.stack = None
        self.layout = None

    def setup_and_check(self, data, title="", readonly=False, xlabels=None, ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)
        if data.size == 0:
            self.error(_("Array is empty"))
            return False
        if data.ndim > 2:
            self.error(_("Arrays with more than 2 dimensions " "are not supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(_("The 'xlabels' argument length " "do no match array column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(_("The 'ylabels' argument length " "do no match array row number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith("string") and not dtn.startswith("unicode"):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(get_icon("arredit.png"))
        if title:
            title = unicode(title)  # in case title is not a string
        else:
            title = _("Array editor")
        if readonly:
            title += " (" + _("read only") + ")"
        self.setWindowTitle(title)
        self.resize(600, 500)

        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(ArrayEditorWidget(self, data[name], readonly, xlabels, ylabels))
        elif is_masked_array:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.data, readonly, xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels))
        else:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
        self.arraywidget = self.stack.currentWidget()
        self.connect(self.stack, SIGNAL("currentChanged(int)"), self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array:
            if is_record_array:
                btn_layout.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not isinstance(title, basestring):
                            title = repr(title)
                        text += " - " + title
                    names.append(text)
            else:
                names = [_("Masked data"), _("Data"), _("Mask")]
            ra_combo = QComboBox(self)
            self.connect(ra_combo, SIGNAL("currentIndexChanged(int)"), self.stack.setCurrentIndex)
            ra_combo.addItems(names)
            btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel(_("<u>Warning</u>: changes are applied separately"))
                label.setToolTip(
                    _(
                        "For performance reasons, changes applied "
                        "to masked array won't be reflected in "
                        "array's data (and vice-versa)."
                    )
                )
                btn_layout.addWidget(label)
            btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)

        self.setMinimumSize(400, 300)

        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)

        return True

    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)

    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()
        QDialog.accept(self)

    def get_value(self):
        """Return modified array -- this is *not* a copy"""
        # It is import to avoid accessing Qt C++ object as it has probably
        # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
        return self.data

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, _("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
Example #12
0
class SideBar(QWidget):
    """ Sidebar with a widget area which is hidden or shown.
        On by clicking any tab, off by clicking the current tab.
    """

    North = 0
    East = 1
    South = 2
    West = 3

    def __init__(self, orientation=2, parent=None):
        QWidget.__init__(self, parent)

        self.__tabBar = QTabBar()
        self.__tabBar.setDrawBase(True)
        self.__tabBar.setShape(QTabBar.RoundedNorth)
        self.__tabBar.setFocusPolicy(Qt.NoFocus)
        self.__tabBar.setUsesScrollButtons(True)
        self.__tabBar.setElideMode(1)
        self.__stackedWidget = QStackedWidget(self)
        self.__stackedWidget.setContentsMargins(0, 0, 0, 0)
        self.barLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.barLayout.setMargin(0)
        self.layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.layout.setMargin(0)
        self.layout.setSpacing(0)
        self.barLayout.addWidget(self.__tabBar)
        self.layout.addLayout(self.barLayout)
        self.layout.addWidget(self.__stackedWidget)
        self.setLayout(self.layout)

        self.__minimized = False
        self.__minSize = 0
        self.__maxSize = 0
        self.__bigSize = QSize()

        self.splitter = None

        self.__tabBar.installEventFilter(self)

        self.__orientation = orientation
        self.setOrientation(orientation)

        self.__tabBar.currentChanged.connect(
            self.__stackedWidget.setCurrentIndex)
        return

    def setSplitter(self, splitter):
        """ Set the splitter managing the sidebar """
        self.splitter = splitter
        return

    def __getIndex(self):
        " Provides the widget index in splitters "
        if self.__orientation == SideBar.West:
            return 0
        if self.__orientation == SideBar.East:
            return 2
        if self.__orientation == SideBar.South:
            return 1
        return 0

    def __getWidget(self):
        " Provides a reference to the widget "
        return self.splitter.widget(self.__getIndex())

    def shrink(self):
        """ Shrink the sidebar """
        if self.__minimized:
            return

        self.__minimized = True
        self.__bigSize = self.size()
        if self.__orientation in [SideBar.North, SideBar.South]:
            self.__minSize = self.minimumHeight()
            self.__maxSize = self.maximumHeight()
        else:
            self.__minSize = self.minimumWidth()
            self.__maxSize = self.maximumWidth()

        self.__stackedWidget.hide()

        sizes = self.splitter.sizes()
        selfIndex = self.__getIndex()

        if self.__orientation in [SideBar.North, SideBar.South]:
            newHeight = self.__tabBar.minimumSizeHint().height()
            self.setFixedHeight(newHeight)

            diff = sizes[selfIndex] - newHeight
            sizes[selfIndex] = newHeight
        else:
            newWidth = self.__tabBar.minimumSizeHint().width()
            self.setFixedWidth(newWidth)

            diff = sizes[selfIndex] - newWidth
            sizes[selfIndex] = newWidth

        if selfIndex == 0:
            sizes[1] += diff
        else:
            sizes[selfIndex - 1] += diff

        self.splitter.setSizes(sizes)
        return

    def expand(self):
        """ Expand the sidebar """
        if not self.__minimized:
            return

        self.__minimized = False
        self.__stackedWidget.show()
        self.resize(self.__bigSize)

        sizes = self.splitter.sizes()
        selfIndex = self.__getIndex()

        if self.__orientation in [SideBar.North, SideBar.South]:
            self.setMinimumHeight(self.__minSize)
            self.setMaximumHeight(self.__maxSize)

            diff = self.__bigSize.height() - sizes[selfIndex]
            sizes[selfIndex] = self.__bigSize.height()
        else:
            self.setMinimumWidth(self.__minSize)
            self.setMaximumWidth(self.__maxSize)

            diff = self.__bigSize.width() - sizes[selfIndex]
            sizes[selfIndex] = self.__bigSize.width()

        if selfIndex == 0:
            sizes[1] -= diff
        else:
            sizes[selfIndex - 1] -= diff

        self.splitter.setSizes(sizes)
        return

    def isMinimized(self):
        """ Provides the minimized state """
        return self.__minimized

    def eventFilter(self, obj, evt):
        """ Handle click events for the tabbar """

        if obj == self.__tabBar:
            if evt.type() == QEvent.MouseButtonPress:
                pos = evt.pos()

                index = self.__tabBar.count() - 1
                while index >= 0:
                    if self.__tabBar.tabRect(index).contains(pos):
                        break
                    index -= 1

                if index == self.__tabBar.currentIndex():
                    if self.isMinimized():
                        self.expand()
                    else:
                        self.shrink()
                    return True

                elif self.isMinimized():
                    if self.isTabEnabled(index):
                        self.expand()

        return QWidget.eventFilter(self, obj, evt)

    def addTab(self, widget, iconOrLabel, label=None):
        """ Add a tab to the sidebar """

        if label:
            self.__tabBar.addTab(iconOrLabel, label)
        else:
            self.__tabBar.addTab(iconOrLabel)
        self.__stackedWidget.addWidget(widget)
        return

    def insertTab(self, index, widget, iconOrLabel, label=None):
        """ Insert a tab into the sidebar """

        if label:
            self.__tabBar.insertTab(index, iconOrLabel, label)
        else:
            self.__tabBar.insertTab(index, iconOrLabel)
        self.__stackedWidget.insertWidget(index, widget)
        return

    def removeTab(self, index):
        """ Remove a tab """

        self.__stackedWidget.removeWidget(self.__stackedWidget.widget(index))
        self.__tabBar.removeTab(index)
        return

    def clear(self):
        """ Remove all tabs """

        while self.count() > 0:
            self.removeTab(0)
        return

    def prevTab(self):
        """ Show the previous tab """

        index = self.currentIndex() - 1
        if index < 0:
            index = self.count() - 1

        self.setCurrentIndex(index)
        self.currentWidget().setFocus()
        return

    def nextTab(self):
        """ Show the next tab """

        index = self.currentIndex() + 1
        if index >= self.count():
            index = 0

        self.setCurrentIndex(index)
        self.currentWidget().setFocus()
        return

    def count(self):
        """ Provides the number of tabs """

        return self.__tabBar.count()

    def currentIndex(self):
        """ Provides the index of the current tab """

        return self.__stackedWidget.currentIndex()

    def setCurrentIndex(self, index):
        """ Switch to the certain tab """

        if index >= self.currentIndex():
            return

        self.__tabBar.setCurrentIndex(index)
        self.__stackedWidget.setCurrentIndex(index)
        if self.isMinimized():
            self.expand()
        return

    def currentWidget(self):
        """ Provide a reference to the current widget """

        return self.__stackedWidget.currentWidget()

    def setCurrentWidget(self, widget):
        """ Set the current widget """

        self.__stackedWidget.setCurrentWidget(widget)
        self.__tabBar.setCurrentIndex(self.__stackedWidget.currentIndex())
        if self.isMinimized():
            self.expand()
        return

    def indexOf(self, widget):
        """ Provides the index of the given widget """

        return self.__stackedWidget.indexOf(widget)

    def isTabEnabled(self, index):
        """ Check if the tab is enabled """

        return self.__tabBar.isTabEnabled(index)

    def setTabEnabled(self, index, enabled):
        """ Set the enabled state of the tab """

        self.__tabBar.setTabEnabled(index, enabled)
        return

    def orientation(self):
        """ Provides the orientation of the sidebar """

        return self.__orientation

    def setOrientation(self, orient):
        """ Set the orientation of the sidebar """

        if orient == SideBar.North:
            self.__tabBar.setShape(QTabBar.RoundedNorth)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        elif orient == SideBar.East:
            self.__tabBar.setShape(QTabBar.RoundedEast)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.RightToLeft)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        elif orient == SideBar.South:
            self.__tabBar.setShape(QTabBar.RoundedSouth)
            self.barLayout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setDirection(QBoxLayout.BottomToTop)
            self.layout.setAlignment(self.barLayout, Qt.AlignLeft)
        else:
            # default
            orient = SideBar.West
            self.__tabBar.setShape(QTabBar.RoundedWest)
            self.barLayout.setDirection(QBoxLayout.TopToBottom)
            self.layout.setDirection(QBoxLayout.LeftToRight)
            self.layout.setAlignment(self.barLayout, Qt.AlignTop)
        self.__orientation = orient
        return

    def tabIcon(self, index):
        """ Provide the icon of the tab """

        return self.__tabBar.tabIcon(index)

    def setTabIcon(self, index, icon):
        """ Set the icon of the tab """

        self.__tabBar.setTabIcon(index, icon)
        return

    def tabText(self, index):
        """ Provide the text of the tab """

        return self.__tabBar.tabText(index)

    def setTabText(self, index, text):
        """ Set the text of the tab """

        self.__tabBar.setTabText(index, text)
        return

    def tabToolTip(self, index):
        """ Provide the tooltip text of the tab """

        return self.__tabBar.tabToolTip(index)

    def setTabToolTip(self, index, tip):
        """ Set the tooltip text of the tab """

        self.__tabBar.setTabToolTip(index, tip)
        return

    def tabWhatsThis(self, index):
        """ Provide the WhatsThis text of the tab """

        return self.__tabBar.tabWhatsThis(index)

    def setTabWhatsThis(self, index, text):
        """ Set the WhatsThis text for the tab """

        self.__tabBar.setTabWhatsThis(index, text)
        return

    def widget(self, index):
        """ Provides the reference to the widget (QWidget) """

        return self.__stackedWidget.widget(index)
Example #13
0
class SideBar( QWidget ):
    """ Sidebar with a widget area which is hidden or shown.
        On by clicking any tab, off by clicking the current tab.
    """

    North = 0
    East  = 1
    South = 2
    West  = 3

    def __init__( self, orientation = 2, parent = None ):
        QWidget.__init__( self, parent )

        self.__tabBar = QTabBar()
        self.__tabBar.setDrawBase( True )
        self.__tabBar.setShape( QTabBar.RoundedNorth )
        self.__tabBar.setFocusPolicy( Qt.NoFocus )
        self.__tabBar.setUsesScrollButtons( True )
        self.__tabBar.setElideMode( 1 )
        self.__stackedWidget = QStackedWidget( self )
        self.__stackedWidget.setContentsMargins( 0, 0, 0, 0 )
        self.barLayout = QBoxLayout( QBoxLayout.LeftToRight )
        self.barLayout.setMargin( 0 )
        self.layout = QBoxLayout( QBoxLayout.TopToBottom )
        self.layout.setMargin( 0 )
        self.layout.setSpacing( 0 )
        self.barLayout.addWidget( self.__tabBar )
        self.layout.addLayout( self.barLayout )
        self.layout.addWidget( self.__stackedWidget )
        self.setLayout( self.layout )

        self.__minimized = False
        self.__minSize = 0
        self.__maxSize = 0
        self.__bigSize = QSize()

        self.splitter = None

        self.__tabBar.installEventFilter( self )

        self.__orientation = orientation
        self.setOrientation( orientation )

        self.__tabBar.currentChanged.connect(
                                        self.__stackedWidget.setCurrentIndex )
        return

    def setSplitter( self, splitter ):
        """ Set the splitter managing the sidebar """
        self.splitter = splitter
        return

    def __getIndex( self ):
        " Provides the widget index in splitters "
        if self.__orientation == SideBar.West:
            return 0
        if self.__orientation == SideBar.East:
            return 2
        if self.__orientation == SideBar.South:
            return 1
        return 0

    def __getWidget( self ):
        " Provides a reference to the widget "
        return self.splitter.widget( self.__getIndex() )

    def shrink( self ):
        """ Shrink the sidebar """
        if self.__minimized:
            return

        self.__minimized = True
        self.__bigSize = self.size()
        if self.__orientation in [ SideBar.North, SideBar.South ]:
            self.__minSize = self.minimumHeight()
            self.__maxSize = self.maximumHeight()
        else:
            self.__minSize = self.minimumWidth()
            self.__maxSize = self.maximumWidth()

        self.__stackedWidget.hide()

        sizes = self.splitter.sizes()
        selfIndex = self.__getIndex()

        if self.__orientation in [ SideBar.North, SideBar.South ]:
            newHeight = self.__tabBar.minimumSizeHint().height()
            self.setFixedHeight( newHeight )

            diff = sizes[ selfIndex ] - newHeight
            sizes[ selfIndex ] = newHeight
        else:
            newWidth = self.__tabBar.minimumSizeHint().width()
            self.setFixedWidth( newWidth )

            diff = sizes[ selfIndex ] - newWidth
            sizes[ selfIndex ] = newWidth

        if selfIndex == 0:
            sizes[ 1 ] += diff
        else:
            sizes[ selfIndex - 1 ] += diff

        self.splitter.setSizes( sizes )
        return

    def expand( self ):
        """ Expand the sidebar """
        if not self.__minimized:
            return

        self.__minimized = False
        self.__stackedWidget.show()
        self.resize( self.__bigSize )

        sizes = self.splitter.sizes()
        selfIndex = self.__getIndex()

        if self.__orientation in [ SideBar.North, SideBar.South ]:
            self.setMinimumHeight( self.__minSize )
            self.setMaximumHeight( self.__maxSize )

            diff = self.__bigSize.height() - sizes[ selfIndex ]
            sizes[ selfIndex ] = self.__bigSize.height()
        else:
            self.setMinimumWidth( self.__minSize )
            self.setMaximumWidth( self.__maxSize )

            diff = self.__bigSize.width() - sizes[ selfIndex ]
            sizes[ selfIndex ] = self.__bigSize.width()

        if selfIndex == 0:
            sizes[ 1 ] -= diff
        else:
            sizes[ selfIndex - 1 ] -= diff

        self.splitter.setSizes( sizes )
        return

    def isMinimized( self ):
        """ Provides the minimized state """
        return self.__minimized

    def eventFilter( self, obj, evt ):
        """ Handle click events for the tabbar """

        if obj == self.__tabBar:
            if evt.type() == QEvent.MouseButtonPress:
                pos = evt.pos()

                index = self.__tabBar.count() - 1
                while index >= 0:
                    if self.__tabBar.tabRect( index ).contains( pos ):
                        break
                    index -= 1

                if index == self.__tabBar.currentIndex():
                    if self.isMinimized():
                        self.expand()
                    else:
                        self.shrink()
                    return True

                elif self.isMinimized():
                    if self.isTabEnabled( index ):
                        self.expand()

        return QWidget.eventFilter( self, obj, evt )

    def addTab( self, widget, iconOrLabel, label = None ):
        """ Add a tab to the sidebar """

        if label:
            self.__tabBar.addTab( iconOrLabel, label )
        else:
            self.__tabBar.addTab( iconOrLabel )
        self.__stackedWidget.addWidget( widget )
        return

    def insertTab( self, index, widget, iconOrLabel, label = None ):
        """ Insert a tab into the sidebar """

        if label:
            self.__tabBar.insertTab( index, iconOrLabel, label )
        else:
            self.__tabBar.insertTab( index, iconOrLabel )
        self.__stackedWidget.insertWidget( index, widget )
        return

    def removeTab( self, index ):
        """ Remove a tab """

        self.__stackedWidget.removeWidget( self.__stackedWidget.widget( index ) )
        self.__tabBar.removeTab( index )
        return

    def clear( self ):
        """ Remove all tabs """

        while self.count() > 0:
            self.removeTab( 0 )
        return

    def prevTab( self ):
        """ Show the previous tab """

        index = self.currentIndex() - 1
        if index < 0:
            index = self.count() - 1

        self.setCurrentIndex( index )
        self.currentWidget().setFocus()
        return

    def nextTab( self ):
        """ Show the next tab """

        index = self.currentIndex() + 1
        if index >= self.count():
            index = 0

        self.setCurrentIndex( index )
        self.currentWidget().setFocus()
        return

    def count( self ):
        """ Provides the number of tabs """

        return self.__tabBar.count()

    def currentIndex( self ):
        """ Provides the index of the current tab """

        return self.__stackedWidget.currentIndex()

    def setCurrentIndex( self, index ):
        """ Switch to the certain tab """

        if index >= self.currentIndex():
            return

        self.__tabBar.setCurrentIndex( index )
        self.__stackedWidget.setCurrentIndex(index)
        if self.isMinimized():
            self.expand()
        return

    def currentWidget( self ):
        """ Provide a reference to the current widget """

        return self.__stackedWidget.currentWidget()

    def setCurrentWidget( self, widget ):
        """ Set the current widget """

        self.__stackedWidget.setCurrentWidget( widget )
        self.__tabBar.setCurrentIndex( self.__stackedWidget.currentIndex() )
        if self.isMinimized():
            self.expand()
        return

    def indexOf( self, widget ):
        """ Provides the index of the given widget """

        return self.__stackedWidget.indexOf( widget )

    def isTabEnabled( self, index ):
        """ Check if the tab is enabled """

        return self.__tabBar.isTabEnabled( index )

    def setTabEnabled( self, index, enabled ):
        """ Set the enabled state of the tab """

        self.__tabBar.setTabEnabled( index, enabled )
        return

    def orientation( self ):
        """ Provides the orientation of the sidebar """

        return self.__orientation

    def setOrientation( self, orient ):
        """ Set the orientation of the sidebar """

        if orient == SideBar.North:
            self.__tabBar.setShape( QTabBar.RoundedNorth )
            self.barLayout.setDirection( QBoxLayout.LeftToRight )
            self.layout.setDirection( QBoxLayout.TopToBottom )
            self.layout.setAlignment( self.barLayout, Qt.AlignLeft )
        elif orient == SideBar.East:
            self.__tabBar.setShape( QTabBar.RoundedEast )
            self.barLayout.setDirection( QBoxLayout.TopToBottom )
            self.layout.setDirection( QBoxLayout.RightToLeft )
            self.layout.setAlignment( self.barLayout, Qt.AlignTop )
        elif orient == SideBar.South:
            self.__tabBar.setShape( QTabBar.RoundedSouth )
            self.barLayout.setDirection( QBoxLayout.LeftToRight )
            self.layout.setDirection( QBoxLayout.BottomToTop )
            self.layout.setAlignment( self.barLayout, Qt.AlignLeft )
        else:
            # default
            orient = SideBar.West
            self.__tabBar.setShape( QTabBar.RoundedWest )
            self.barLayout.setDirection( QBoxLayout.TopToBottom )
            self.layout.setDirection( QBoxLayout.LeftToRight )
            self.layout.setAlignment( self.barLayout, Qt.AlignTop )
        self.__orientation = orient
        return

    def tabIcon( self, index ):
        """ Provide the icon of the tab """

        return self.__tabBar.tabIcon( index )

    def setTabIcon( self, index, icon ):
        """ Set the icon of the tab """

        self.__tabBar.setTabIcon( index, icon )
        return

    def tabText( self, index ):
        """ Provide the text of the tab """

        return self.__tabBar.tabText( index )

    def setTabText( self, index, text ):
        """ Set the text of the tab """

        self.__tabBar.setTabText( index, text )
        return

    def tabToolTip( self, index ):
        """ Provide the tooltip text of the tab """

        return self.__tabBar.tabToolTip( index )

    def setTabToolTip( self, index, tip ):
        """ Set the tooltip text of the tab """

        self.__tabBar.setTabToolTip( index, tip )
        return

    def tabWhatsThis( self, index ):
        """ Provide the WhatsThis text of the tab """

        return self.__tabBar.tabWhatsThis( index )

    def setTabWhatsThis( self, index, text ):
        """ Set the WhatsThis text for the tab """

        self.__tabBar.setTabWhatsThis( index, text )
        return

    def widget( self, index ):
        """ Provides the reference to the widget (QWidget) """

        return self.__stackedWidget.widget( index )
Example #14
0
class Container(QSplitter):

    def __init__(self, orientation=Qt.Vertical):
        super(Container, self).__init__(orientation)
        self.__last_open_folder = None
        self.__filename = ""
        self.__created = False
        self.__modified = False
        vbox = QVBoxLayout(self)
        vbox.setContentsMargins(0, 0, 0, 0)
        # Stacked
        self.stacked = QStackedWidget()
        vbox.addWidget(self.stacked)

        # Table
        self.table_widget = table_widget.TableWidget()

        Pireal.load_service("container", self)

    def create_data_base(self, filename=''):
        """ This function opens or creates a database

        :param filename: Database filename
        """

        if self.__created:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Solo puede tener una base de datos "
                                         "abierta a la vez."))
            return
        if not filename:
            db_name, ok = QInputDialog.getText(self, self.tr("Nueva DB"),
                                               self.tr("Nombre:"))
            if not ok:
                return
        else:
            # From file
            try:
                db_name, data = file_manager.open_database(filename)
            except Exception as reason:
                QMessageBox.critical(self, self.tr("Error!"),
                                     reason.__str__())
                return

            self.table_widget.add_data_base(data)

        # Remove Start Page widget
        if isinstance(self.stacked.widget(0), start_page.StartPage):
            self.stacked.removeWidget(self.stacked.widget(0))
        self.stacked.addWidget(self.table_widget)
        # Title
        pireal = Pireal.get_service("pireal")
        pireal.change_title(db_name)
        # Enable QAction's
        pireal.enable_disable_db_actions()
        self.__created = True

    def create_new_relation(self):
        dialog = new_relation_dialog.NewRelationDialog(self)
        dialog.show()

    def remove_relation(self):
        lateral = Pireal.get_service("lateral")
        rname = lateral.get_relation_name()
        if not rname:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("No se ha seleccionado ninguna "
                                         "relación."))
            return
        r = QMessageBox.question(self, self.tr("Confirmación"),
                                 self.tr("Seguro que quieres eliminar la "
                                         "relación <b>{}</b>").format(rname),
                                             QMessageBox.Yes | QMessageBox.No)
        if r == QMessageBox.No:
            return
        index = lateral.current_index()
        # Remove table
        self.table_widget.remove_table(index)
        # Remove item from list widget
        lateral.remove_item(index)

    def new_query(self, filename=''):
        query_widget = Pireal.get_service("query_widget")
        self.addWidget(query_widget)
        if not query_widget.isVisible():
            query_widget.show()
        pireal = Pireal.get_service("pireal")
        pireal.enable_disable_query_actions()
        query_widget.new_query(filename)

        self.connect(query_widget,
                     SIGNAL("currentEditorSaved(QPlainTextEdit)"),
                     self.save_query)

    @property
    def modified(self):
        return self.__modified

    def show_start_page(self):
        sp = start_page.StartPage()
        self.stacked.addWidget(sp)

    def close_db(self):
        """ Close data base """

        widget = self.stacked.currentWidget()
        if isinstance(widget, table_widget.TableWidget):
            # Clear list of relations
            lateral = Pireal.get_service("lateral")
            lateral.clear_items()
            lateral.hide()
            # Close table widget
            self.stacked.removeWidget(widget)
            # Add start page
            self.show_start_page()

            self.__created = False

    def save_query(self, weditor=None):
        if weditor is None:
            query_widget = Pireal.get_service("query_widget")
            # Editor instance
            weditor = query_widget.get_active_editor()
        if weditor.rfile.is_new:
            return self.save_query_as(weditor)
        content = weditor.toPlainText()
        weditor.rfile.write(content)
        weditor.document().setModified(False)

        self.emit(SIGNAL("currentFileSaved(QString)"),
                  self.tr("Archivo guardado: {}").format(weditor.filename))

    def open_file(self):

        if self.__last_open_folder is None:
            directory = os.path.expanduser("~")
        else:
            directory = self.__last_open_folder
        filename = QFileDialog.getOpenFileName(self, self.tr("Abrir Archivo"),
                                               directory, settings.DBFILE,
                                               QFileDialog.DontUseNativeDialog)
        if not filename:
            return
        # Save folder
        self.__last_open_folder = file_manager.get_path(filename)

        ext = file_manager.get_extension(filename)
        if ext == '.pqf':
            # Query file
            self.new_query(filename)
        elif ext == '.rdb':
            self.load_rdb_database(file_manager.read_rdb_file(filename))
        else:
            self.create_data_base(filename)

    def load_rdb_database(self, content):
        csv_content = ""
        for line in content.splitlines():
            if line.startswith('@'):
                csv_content += '@'
                portion = line.split('(')
                name = portion[0][1:]
                csv_content += name + ':'
                for i in portion[1].split(','):
                    if not i.startswith(' '):
                        field = i.split('/')[0].strip()
                        csv_content += field + ','
            else:
                if not line:
                    continue
                csv_content += line
            csv_content += '\n'

        self.table_widget.add_table_from_rdb_content(csv_content)

    def save_query_as(self, editor=None):
        if editor is None:
            query_widget = Pireal.get_service("query_widget")
            editor = query_widget.get_active_editor()
        directory = os.path.expanduser("~")
        filename = QFileDialog.getSaveFileName(self,
                                               self.tr("Guardar Archivo"),
                                               directory)
        if not filename:
            return
        content = editor.toPlainText()
        editor.rfile.write(content, filename)
        editor.document().setModified(False)

    def load_relation(self, filenames=[]):
        """ Load relation from file """

        if not filenames:
            native_dialog = QFileDialog.DontUseNativeDialog
            if self.__last_open_folder is None:
                directory = os.path.expanduser("~")
            else:
                directory = self.__last_open_folder
            ffilter = settings.RFILES.split(';;')[-1]
            filenames = QFileDialog.getOpenFileNames(self,
                                                     self.tr("Abrir Archivo"),
                                                     directory, ffilter,
                                                     native_dialog)
            if not filenames:
                return
            # Save folder
            self.__last_open_folder = file_manager.get_path(filenames[0])
            self.__modified = True

        # Load tables
        self.table_widget.load_relation(filenames)

    def execute_queries(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.execute_queries()

    def undo_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.undo()

    def redo_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.redo()

    def cut_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.cut()

    def copy_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.copy()

    def paste_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.paste()

    def check_opened_query_files(self):
        query_widget = Pireal.get_service("query_widget")
        return query_widget.opened_files()
Example #15
0
class FltsSearchDockWidget(QDockWidget):
    """
    Dock widget for showing search widgets with each widget corresponding to
    a search configuration.
    """
    def __init__(self, *args, **kwargs):
        super(FltsSearchDockWidget, self).__init__(*args, **kwargs)
        self.setAllowedAreas(Qt.BottomDockWidgetArea)
        self._search_reg = SearchConfigurationRegistry.instance()
        self._stack_widget = QStackedWidget(self)
        self.setWidget(self._stack_widget)

        # Index data source to their location in the stack widget
        self._search_widget_idx = dict()

    def show_search_widget(self, data_source):
        """
        Shows the search widget associated with the given data source. If
        not found then it will create a new one by using the factory
        method in the search configuration.
        :param data_source: Data source name.
        :type data_source: str
        :return: Returns True if the operation was successful else False. It
        will be false if the data source is not found in the registry.
        :rtype: bool
        """
        config = self._search_reg.search_config(data_source)
        if not config:
            return False

        # Set current search widget
        self._set_current_widget(config)

        return True

    def _set_current_widget(self, config):
        # Updates dock widget based on the specified config.
        data_source = config.data_source

        # Create widget if it does not exist in the stack
        if not data_source in self._search_widget_idx:
            search_widget = config.create_widget()
            idx = self._stack_widget.addWidget(search_widget)
            self._search_widget_idx[data_source] = idx
        else:
            idx = self._search_widget_idx[data_source]

        self._stack_widget.setCurrentIndex(idx)

        # Set title
        self.setWindowTitle(u'Search {0}'.format(config.display_name))

    def current_widget(self):
        """
        :return: Returns the current search widget or None if there are no
        widgets in the stack.
        :rtype: QWidget
        """
        return self._stack_widget.currentWidget()

    def clear(self):
        """
        Removes all the search widgets and resets the indices.
        """
        while self._stack_widget.count() > 0:
            sw = self._stack_widget.widget(0)
            self._stack_widget.removeWidget(sw)
            del sw

        self._search_widget_idx = dict()
Example #16
0
class ArrayEditor(QDialog):
    """Array Editor Dialog"""    
    def __init__(self, parent=None):
        super(ArrayEditor, self).__init__(parent)
    
    def setup_and_check(self, data, title='', xy=False, readonly=False):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.arraywidget = None
        self.is_record_array = data.dtype.names is not None
        if data.ndim > 2:
            self.error(self.tr("Arrays with more than 2 dimensions "
                               "are not supported"))
            return False
        if not self.is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('string') \
               and not dtn.startswith('unicode'):
                arr = self.tr("%1 arrays").arg(data.dtype.name)
                self.error(self.tr("%1 are currently not supported").arg(arr))
                return False
        
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(get_icon('arredit.png'))
        title = self.tr("Array editor") + \
                "%s" % (" - "+str(title) if str(title) else "")
        if readonly:
            title += ' (' + self.tr('read only') + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)
        
        # Stack widget
        self.stack = QStackedWidget(self)
        if self.is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(ArrayEditorWidget(self, data[name],
                                                       xy, readonly))
        else:
            self.stack.addWidget(ArrayEditorWidget(self, data, xy, readonly))
        self.arraywidget = self.stack.currentWidget()
        self.connect(self.stack, SIGNAL('currentChanged(int)'),
                     self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if self.is_record_array:
            btn_layout.addWidget(QLabel(self.tr("Record array fields:")))
            ra_combo = QComboBox(self)
            self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
                         self.stack.setCurrentIndex)
            names = []
            for name in data.dtype.names:
                field = data.dtype.fields[name]
                text = name
                if len(field) >= 3:
                    title = field[2]
                    if not isinstance(title, basestring):
                        title = repr(title)
                    text += ' - '+title
                names.append(text)
            ra_combo.addItems(names)
            btn_layout.addWidget(ra_combo)
            btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)
        
        self.setMinimumSize(400, 300)
        
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        
        return True
        
    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)
        
    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()
        QDialog.accept(self)

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, self.tr("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
Example #17
0
class Container(QSplitter):

    def __init__(self, orientation=Qt.Vertical):
        super(Container, self).__init__(orientation)
        self._data_bases = []
        self.__filename = ""
        vbox = QVBoxLayout(self)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.__created = False
        # Stacked
        self.stacked = QStackedWidget()
        vbox.addWidget(self.stacked)

        # Table
        self.table_widget = table_widget.TableWidget()

        Pireal.load_service("container", self)

    def create_data_base(self, filename=''):
        """ This function opens or creates a database

        :param filename: Database filename
        """

        if self.__created:
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Solo puede tener una base de datos "
                                         "abierta a la vez."))
            return
        from_file = False
        if not filename:
            db_name, ok = QInputDialog.getText(self, self.tr("Nueva DB"),
                                               self.tr("Nombre:"))
            if not ok:
                return
        else:
            from_file = True
            # Read database from file
            try:
                data = file_manager.open_database(filename)
            except Exception as reason:
                QMessageBox.critical(self, self.tr("Error!"),
                                     reason.__str__())
                return
            # This is intended to give support multiple database
            for name, files in data.items():
                db_name = name
        # Remove the start page
        self.stacked.removeWidget(self.stacked.widget(0))
        self.stacked.addWidget(self.table_widget)
        pireal = Pireal.get_service("pireal")
        # Title
        pireal.change_title(db_name)
        if from_file:
            self.load_relation(files)
        # Enable QAction's
        pireal.enable_disable_db_actions()
        self.__created = True

    def create_new_relation(self):
        dialog = new_relation_dialog.NewRelationDialog(self)
        dialog.show()

    def remove_relation(self):
        lateral = Pireal.get_service("lateral")
        lateral.remove_table()

    def new_query(self, filename=''):
        query_widget = Pireal.get_service("query_widget")
        self.addWidget(query_widget)
        if not query_widget.isVisible():
            query_widget.show()
        pireal = Pireal.get_service("pireal")
        pireal.enable_disable_query_actions()
        query_widget.new_query(filename)

        self.connect(query_widget,
                     SIGNAL("currentEditorSaved(QPlainTextEdit)"),
                     self.save_query)

    def show_start_page(self):
        sp = start_page.StartPage()
        self.stacked.addWidget(sp)

    def close_db(self):
        widget = self.stacked.currentWidget()
        if isinstance(widget, table_widget.TableWidget):
            self.close()

    def save_query(self, weditor=None):
        if weditor is None:
            query_widget = Pireal.get_service("query_widget")
            # Editor instance
            weditor = query_widget.get_active_editor()
        if weditor.rfile.is_new:
            return self.save_query_as(weditor)
        content = weditor.toPlainText()
        weditor.rfile.write(content)
        weditor.document().setModified(False)

        self.emit(SIGNAL("currentFileSaved(QString)"),
                  self.tr("Archivo guardado: {}").format(weditor.filename))

    def open_file(self):

        directory = os.path.expanduser("~")
        filename = QFileDialog.getOpenFileName(self, self.tr("Abrir Archivo"),
                                               directory, settings.DBFILE,
                                               QFileDialog.DontUseNativeDialog)
        if not filename:
            return
        ext = file_manager.get_extension(filename)
        if ext == '.pqf':
            # Query file
            self.new_query(filename)
        else:
            self.create_data_base(filename)

    def save_query_as(self, editor=None):
        if editor is None:
            query_widget = Pireal.get_service("query_widget")
            editor = query_widget.get_active_editor()
        directory = os.path.expanduser("~")
        filename = QFileDialog.getSaveFileName(self,
                                               self.tr("Guardar Archivo"),
                                               directory)
        if not filename:
            return
        content = editor.toPlainText()
        editor.rfile.write(content, filename)
        editor.document().setModified(False)

    def load_relation(self, filenames=[]):
        """ Load relation from file """

        import csv
        from PyQt4.QtGui import QTableWidgetItem, QTableWidget
        from src.core import relation

        if not filenames:
            native_dialog = QFileDialog.DontUseNativeDialog
            directory = os.path.expanduser("~")
            ffilter = settings.RFILES.split(';;')[-1]
            filenames = QFileDialog.getOpenFileNames(self,
                                                     self.tr("Abrir Archivo"),
                                                     directory, ffilter,
                                                     native_dialog)
            if not filenames:
                return
        lateral = Pireal.get_service("lateral")
        for filename in filenames:
            rel = relation.Relation(filename)
            relation_name = os.path.splitext(os.path.basename(filename))[0]
            self.table_widget.relations[relation_name] = rel
            table = QTableWidget()
            with open(filename, newline='') as f:
                table.setRowCount(0)
                table.setColumnCount(0)
                csv_reader = csv.reader(f)
                for row_data in csv_reader:
                    row = table.rowCount()
                    table.setColumnCount(len(row_data))
                    for column, data in enumerate(row_data):
                        item = QTableWidgetItem()
                        item.setText(data)
                        if row == 0:
                            table.setHorizontalHeaderItem(column, item)
                        else:
                            table.setItem(row - 1, column, item)
                    table.insertRow(row)
                table.removeRow(table.rowCount() - 1)
            self.table_widget.stacked.addWidget(table)
        #FIXME: names
        names = [os.path.splitext(os.path.basename(i))[0]
                 for i in filenames]
        lateral.add_item_list(names)
        lateral.show()

    def execute_queries(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.execute_queries()

    def undo_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.undo()

    def redo_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.redo()

    def cut_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.cut()

    def copy_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.copy()

    def paste_action(self):
        query_widget = Pireal.get_service("query_widget")
        query_widget.paste()

    def check_opened_query_files(self):
        query_widget = Pireal.get_service("query_widget")
        return query_widget.opened_files()
Example #18
0
class ArrayEditor(QDialog):
    """Array Editor Dialog"""    
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        self.data = None
        self.arraywidget = None
        self.stack = None
        self.layout = None
    
    def setup_and_check(self, data, title='', readonly=False,
                        xlabels=None, ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)
        if data.size == 0:
            self.error(_("Array is empty"))
            return False
        if data.ndim > 2:
            self.error(_("Arrays with more than 2 dimensions "
                               "are not supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(_("The 'xlabels' argument length "
						 	   "do no match array column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(_("The 'ylabels' argument length "
							   "do no match array row number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('string') \
               and not dtn.startswith('unicode'):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False
        
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(get_icon('arredit.png'))
        if title:
            title = unicode(title) # in case title is not a string
        else:
            title = _("Array editor")
        if readonly:
            title += ' (' + _('read only') + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)
        
        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(ArrayEditorWidget(self, data[name],
                                                   readonly, xlabels, ylabels))
        elif is_masked_array:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly,
                                                   xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.data, readonly,
                                                   xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.mask, readonly,
                                                   xlabels, ylabels))
        else:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly,
                                                   xlabels, ylabels))
        self.arraywidget = self.stack.currentWidget()
        self.connect(self.stack, SIGNAL('currentChanged(int)'),
                     self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array:
            if is_record_array:
                btn_layout.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not isinstance(title, basestring):
                            title = repr(title)
                        text += ' - '+title
                    names.append(text)
            else:
                names = [_('Masked data'), _('Data'), _('Mask')]
            ra_combo = QComboBox(self)
            self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
                         self.stack.setCurrentIndex)
            ra_combo.addItems(names)
            btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel(_("<u>Warning</u>: changes are applied separately"))
                label.setToolTip(_("For performance reasons, changes applied "\
                                   "to masked array won't be reflected in "\
                                   "array's data (and vice-versa)."))
                btn_layout.addWidget(label)
            btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()"))
        self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)
        
        self.setMinimumSize(400, 300)
        
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        
        return True
        
    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)
        
    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()
        QDialog.accept(self)
        
    def get_value(self):
        """Return modified array -- this is *not* a copy"""
        # It is import to avoid accessing Qt C++ object as it has probably
        # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
        return self.data

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, _("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
class CheckAnalysisPuWidget(PuWidget):
    """A widget with checks and analyzes."""

    set_text_statusbar = pyqtSignal(str, int, bool)

    def _setup_self(self):
        """Sets up self."""

        self.setObjectName(u'checkAnalysisPuWidget')

        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName(u'gridLayout')
        self.gridLayout.setColumnStretch(1, 1)

        self._build_widgets()

    def _build_widgets(self):
        """Builds own widgets."""

        self.set_text_statusbar.connect(self.dW.statusBar.set_text)

        self.checkAnalysisLabel = QLabel(self)
        self.checkAnalysisLabel.setObjectName(u'checkAnalysisLabel')
        self.checkAnalysisLabel.setText(u'Kontrola/analýza:')
        self.gridLayout.addWidget(self.checkAnalysisLabel, 0, 0, 1, 1)

        self.checkAnalysisComboBox = QComboBox(self)
        self.checkAnalysisComboBox.setObjectName(u'checkAnalysisComboBox')
        self.gridLayout.addWidget(self.checkAnalysisComboBox, 0, 1, 1, 1)

        perimeterString = u'kontrola - obvodem'
        self.checkAnalysisComboBox.addItem(perimeterString)
        self.checkAnalysisComboBox.setItemData(0, perimeterString,
                                               Qt.ToolTipRole)

        notInSpiString = u'kontrola - není v SPI'
        self.checkAnalysisComboBox.addItem(notInSpiString)
        self.checkAnalysisComboBox.setItemData(
            1, notInSpiString + u' (nová parcela)', Qt.ToolTipRole)

        notInMapString = u'kontrola - není v mapě'
        self.checkAnalysisComboBox.addItem(notInMapString)
        self.checkAnalysisComboBox.setItemData(2, notInMapString,
                                               Qt.ToolTipRole)

        areaString = u'kontrola - výměra nad mezní odchylkou'
        self.checkAnalysisComboBox.addItem(areaString)
        self.checkAnalysisComboBox.setItemData(3, areaString, Qt.ToolTipRole)

        unownedString = u'kontrola - bez vlastníka'
        self.checkAnalysisComboBox.addItem(unownedString)
        self.checkAnalysisComboBox.setItemData(
            4, unownedString + u' (pouze zjednodušená evidence)',
            Qt.ToolTipRole)

        distanceString = u'analýza - měření vzdálenosti'
        self.checkAnalysisComboBox.addItem(distanceString)
        self.checkAnalysisComboBox.setItemData(
            5, distanceString + u' (referenční bod - těžiště parcel)',
            Qt.ToolTipRole)

        bpejString = u'analýza - oceňování podle BPEJ'
        self.checkAnalysisComboBox.addItem(bpejString)
        self.checkAnalysisComboBox.setItemData(6, bpejString, Qt.ToolTipRole)

        self.gridLayout.setRowStretch(1, 1)

        self.checkAnalysisLabelStackedWidget = QStackedWidget(self)
        self.checkAnalysisLabelStackedWidget.setObjectName(
            u'checkAnalysisLabelStackedWidget')
        self.gridLayout.addWidget(self.checkAnalysisLabelStackedWidget, 2, 0,
                                  1, 1)

        self.checkAnalysisStackedWidget = QStackedWidget(self)
        self.checkAnalysisStackedWidget.setObjectName(
            u'checkAnalysisStackedWidget')
        self.gridLayout.addWidget(self.checkAnalysisStackedWidget, 2, 1, 1, 1)

        self.perimeterLabelPuCaWidget = \
            perimeter_pucawidget.PerimeterLabelPuCaWidget(
                self, self.dWName, self.iface, self.dW, self.pluginDir,
                u'perimeterLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.perimeterLabelPuCaWidget)
        self.perimeterPuCaWidget = perimeter_pucawidget.PerimeterPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'perimeterPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.perimeterPuCaWidget)

        self.notInSpiLabelPuCaWidget = \
            notinspi_pucawidget.NotInSpiLabelPuCaWidget(
                self, self.dWName, self.iface, self.dW, self.pluginDir,
                u'notInSpiLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.notInSpiLabelPuCaWidget)
        self.notInSpiPuCaWidget = notinspi_pucawidget.NotInSpiPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'notInSpiPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.notInSpiPuCaWidget)

        self.notInMapLabelPuCaWidget = \
            notinmap_pucawidget.NotInMapLabelPuCaWidget(
                self, self.dWName, self.iface, self.dW, self.pluginDir,
                u'notInMapLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.notInMapLabelPuCaWidget)
        self.notInMapPuCaWidget = notinmap_pucawidget.NotInMapPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'notInMapPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.notInMapPuCaWidget)

        self.areaLabelPuCaWidget = area_pucawidget.AreaLabelPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'areaLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.areaLabelPuCaWidget)
        self.areaPuCaWidget = area_pucawidget.AreaPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'areaPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.areaPuCaWidget)

        self.unownedLabelPuCaWidget = unowned_pucawidget.UnownedLabelPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'unownedLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.unownedLabelPuCaWidget)
        self.unownedPuCaWidget = unowned_pucawidget.UnownedPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'unownedPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.unownedPuCaWidget)

        self.distanceLabelPuCaWidget = \
            distance_pucawidget.DistanceLabelPuCaWidget(
                self, self.dWName, self.iface, self.dW, self.pluginDir,
                u'distanceLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.distanceLabelPuCaWidget)
        self.distancePuCaWidget = distance_pucawidget.DistancePuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'distancePuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.distancePuCaWidget)

        self.bpejLabelPuCaWidget = bpej_pucawidget.BpejLabelPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'bpejLabelPuCaWidget')
        self.checkAnalysisLabelStackedWidget.addWidget(
            self.bpejLabelPuCaWidget)
        self.bpejPuCaWidget = bpej_pucawidget.BpejPuCaWidget(
            self, self.dWName, self.iface, self.dW, self.pluginDir,
            u'bpejPuCaWidget')
        self.checkAnalysisStackedWidget.addWidget(self.bpejPuCaWidget)

        self.checkAnalysisComboBox.currentIndexChanged.connect(
            self.checkAnalysisLabelStackedWidget.setCurrentIndex)
        self.checkAnalysisComboBox.currentIndexChanged.connect(
            self.checkAnalysisStackedWidget.setCurrentIndex)
        self.checkAnalysisComboBox.currentIndexChanged.connect(
            self._set_text_checkAnalysisPushButton)

        self.gridLayout.setRowStretch(3, 1)

        self.checkAnalysisPushButton = QPushButton(self)
        self.checkAnalysisPushButton.setObjectName(u'checkAnalysisPushButton')
        self.checkAnalysisPushButton.clicked.connect(self._run_check)
        self.checkAnalysisPushButton.setText(
            u'Provést kontrolu a vybrat problémové parcely')
        self.gridLayout.addWidget(self.checkAnalysisPushButton, 4, 0, 1, 2)

    def _run_check(self):
        """Starts the current check or analysis.
        
        First it calls a function that checks if there is an active layer
        and if the active layer contains all required columns. If that function
        returns True, check or analysis is executed in a separate thread.
        
        """

        succes, layer = self.dW.check_layer(self)

        if succes:
            self.executeThread = ExecuteThread(layer)
            self.executeThread.started.connect(
                self.checkAnalysisStackedWidget.currentWidget().execute)
            self.executeThread.start()

    def _set_text_checkAnalysisPushButton(self, currentIndex):
        """Sets checkAnalysisPushButton's text.
        
        Sets checkAnalysisPushButton's text according to checkAnalysisComboBox's
        current index.
        
        Args:
            currentIndex (int): Current index of the checkAnalysisComboBox.
        
        """

        if currentIndex <= 4:
            self.checkAnalysisPushButton.setText(
                u'Provést kontrolu a vybrat problémové parcely')
        else:
            self.checkAnalysisPushButton.setText(u'Provést analýzu')