Example #1
0
 def __init__(self, parent, ancestor):
     QTabBar.__init__(self, parent)
     self.ancestor = ancestor
         
     # Dragging tabs
     self.__drag_start_pos = QPoint()
     self.setAcceptDrops(True)
Example #2
0
    def __init__(self, parent, ancestor):
        QTabBar.__init__(self, parent)
        self.ancestor = ancestor

        # Dragging tabs
        self.__drag_start_pos = QPoint()
        self.setAcceptDrops(True)
Example #3
0
        def __init__( self, parent = None ):
            QTabBar.__init__( self, parent )

            self.lineEdit = self.FramelessLineEdit( self )
            self.currentTab = -1

            self.connect( self.lineEdit, SIGNAL( 'returnPressed()' ), self.slotReturnPressed )
 def __init__(self, parent = None):
     """
     Constructor
     
     @param parent reference to the parent widget (QWidget)
     """
     QTabBar.__init__(self, parent)
     self._tabWidget = parent
Example #5
0
 def dragEnterEvent(self, event):
     """Override Qt method"""
     mimeData = event.mimeData()
     formats = mimeData.formats()
     if formats.contains("parent-id") and \
        mimeData.data("parent-id").toLong()[0] == id(self.ancestor):
         event.acceptProposedAction()
     QTabBar.dragEnterEvent(self, event)
Example #6
0
 def dragEnterEvent(self, event):
     """Override Qt method"""
     mimeData = event.mimeData()
     formats = mimeData.formats()
     if formats.contains("parent-id") and \
        mimeData.data("parent-id").toLong()[0] == id(self.ancestor):
         event.acceptProposedAction()
     QTabBar.dragEnterEvent(self, event)
Example #7
0
    def __init__(self, parent=None, *args, **kwargs):
        """
        Reset tab text orientation on initialization

        :param width: Remove default width parameter in kwargs
        :param height: Remove default height parameter in kwargs
        """
        self.tabSize = QSize(kwargs.pop('width', 100), kwargs.pop('height', 25))
        QTabBar.__init__(self, parent, *args, **kwargs)
 def __init__(self, parent):
     " init class custom tab bar "
     QTabBar.__init__(self, parent)
     self._editor = QLineEdit(self)
     self._editor.setToolTip(" Type a Tab Name ")
     self._editor.setWindowFlags(Qt.Popup)
     self._editor.setFocusProxy(self)
     self._editor.editingFinished.connect(self.handleEditingFinished)
     self._editor.installEventFilter(self)
 def mouseMoveEvent(self,event):
     index = 0
     while(index < self.count()):
         if self.tabRect(index).contains(event.pos(),True):
             self.hoveredTab = index
             self.repaint()
             break
         index += 1
     QTabBar.mouseMoveEvent(self,event)
Example #10
0
        def mouseDoubleClickEvent( self, event ):
            QTabBar.mouseDoubleClickEvent( self, event )
            index = self.tabAt( event.pos() )
            if index < 0:
                self.lineEdit.hide()
                return

            self.currentTab = index
            self.lineEdit.show()
            self.lineEdit.setGeometry( self.tabRect( index ) )
            self.lineEdit.setText( self.tabText( index ) )
            self.lineEdit.setFocus()
            self.lineEdit.selectAll()
Example #11
0
 def dropEvent(self, event):
     """Override Qt method"""
     mimeData = event.mimeData()
     index_from = mimeData.data("source-index").toInt()[0]
     index_to = self.tabAt(event.pos())
     if mimeData.data("tabbar-id").toLong()[0] != id(self):
         tabwidget_from = mimeData.data("tabwidget-id").toLong()[0]
         self.emit(SIGNAL("move_tab(long,int,int)"), tabwidget_from,
                   index_from, index_to)
         event.acceptProposedAction()
     elif index_from != index_to:
         self.emit(SIGNAL("move_tab(int,int)"), index_from, index_to)
         event.acceptProposedAction()
     QTabBar.dropEvent(self, event)
Example #12
0
 def dropEvent(self, event):
     """Override Qt method"""
     mimeData = event.mimeData()
     index_from = mimeData.data("source-index").toInt()[0]
     index_to = self.tabAt(event.pos())
     if mimeData.data("tabbar-id").toLong()[0] != id(self):
         tabwidget_from = mimeData.data("tabwidget-id").toLong()[0]
         self.emit(SIGNAL("move_tab(long,int,int)"), 
                   tabwidget_from, index_from, index_to)
         event.acceptProposedAction()
     elif index_from != index_to:
         self.emit(SIGNAL("move_tab(int,int)"), index_from, index_to)
         event.acceptProposedAction()
     QTabBar.dropEvent(self, event)
Example #13
0
 def mouseMoveEvent(self, event):
     """Override Qt method"""
     if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \
        (event.pos() - self.__drag_start_pos).manhattanLength() > \
             QApplication.startDragDistance():
         drag = QDrag(self)
         mimeData = QMimeData()
         mimeData.setData("parent-id", QByteArray.number(id(self.ancestor)))
         mimeData.setData("tabwidget-id",
                          QByteArray.number(id(self.parentWidget())))
         mimeData.setData("tabbar-id", QByteArray.number(id(self)))
         mimeData.setData("source-index", 
                      QByteArray.number(self.tabAt(self.__drag_start_pos)))
         drag.setMimeData(mimeData)
         drag.exec_()
     QTabBar.mouseMoveEvent(self, event)
 def eventFilter(self, widget, event):
     " filter mouse, esc key,  events "
     if (event.type() == QEvent.MouseButtonPress and not self._editor.geometry().contains(event.globalPos())) or (
         event.type() == QEvent.KeyPress and event.key() == Qt.Key_Escape
     ):
         self._editor.hide()
         return True
     return QTabBar.eventFilter(self, widget, event)
Example #15
0
 def mouseMoveEvent(self, event):
     """Override Qt method"""
     if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \
        (event.pos() - self.__drag_start_pos).manhattanLength() > \
             QApplication.startDragDistance():
         drag = QDrag(self)
         mimeData = QMimeData()
         mimeData.setData("parent-id", QByteArray.number(id(self.ancestor)))
         mimeData.setData("tabwidget-id",
                          QByteArray.number(id(self.parentWidget())))
         mimeData.setData("tabbar-id", QByteArray.number(id(self)))
         mimeData.setData(
             "source-index",
             QByteArray.number(self.tabAt(self.__drag_start_pos)))
         drag.setMimeData(mimeData)
         drag.exec_()
     QTabBar.mouseMoveEvent(self, event)
Example #16
0
 def addWidgets(self):
     """Create main layout."""
     logger = self.logger
     logger.debug('adding widgets')
     layout = QVBoxLayout()
     self.setLayout(layout)
     layout.setSpacing(0)
     layout.setContentsMargins(0, 0, 0, 0)
     tabbar = QTabBar(self)
     tabbar.setFocusPolicy(Qt.NoFocus)
     tabbar.setVisible(False)
     tabbar.currentChanged.connect(self.changeVault)
     layout.addWidget(tabbar)
     self.tabbar = tabbar
     stack = QStackedWidget(self)
     layout.addWidget(stack)
     novault = NoVaultWidget(stack)
     stack.addWidget(novault)
     self.stack = stack
Example #17
0
 def mouseMoveEvent(self, event):
     """Override Qt method"""
     if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \
        (event.pos() - self.__drag_start_pos).manhattanLength() > \
             QApplication.startDragDistance():
         drag = QDrag(self)
         mimeData = QMimeData()
         # Converting id's to long to avoid an OverflowError with PySide
         ancestor_id = long(id(self.ancestor))
         parent_widget_id = long(id(self.parentWidget()))
         self_id = long(id(self))
         mimeData.setData("parent-id", QByteArray.number(ancestor_id))
         mimeData.setData("tabwidget-id",
                          QByteArray.number(parent_widget_id))
         mimeData.setData("tabbar-id", QByteArray.number(self_id))
         mimeData.setData("source-index", 
                      QByteArray.number(self.tabAt(self.__drag_start_pos)))
         drag.setMimeData(mimeData)
         drag.exec_()
     QTabBar.mouseMoveEvent(self, event)
 def paintEvent(self,event):
     painter = QPainter(self)
     if self.hasUnderLine:
         rect = self.tabRect(self.hoveredTab)
         linesPath = QPainterPath()
         linesPath.moveTo(QPoint(rect.x()+10,rect.height()-5))
         linesPath.lineTo(QPoint(rect.x()-10+rect.width(),rect.height()-5))
         linesPath.closeSubpath()
         painter.setPen(QPen(QColor(170,200,200),6))
         painter.drawPath(linesPath)
         # 如果不是当前选中的页,在页标签下画线
         if self.hoveredTab != self.currentIndex ():
             if self.isTabEnabled(self.hoveredTab):
                 rect = self.tabRect(self.hoveredTab)
                 linesPath = QPainterPath()
                 linesPath.moveTo(QPoint(rect.x()+10,rect.height()-5))
                 linesPath.lineTo(QPoint(rect.x()-10+rect.width(),rect.height()-5))
                 linesPath.closeSubpath()
                 painter.setPen(QPen(QColor(170,200,200),6))
                 painter.drawPath(linesPath)
     QTabBar.paintEvent(self,event)
Example #19
0
    def dropEvent(self, event):
        """Override Qt method"""
        mimeData = event.mimeData()
        index_from = mimeData.data("source-index").toInt()[0]
        index_to = self.tabAt(event.pos())
        if index_to == -1:
            index_to = self.count()
        if mimeData.data("tabbar-id").toLong()[0] != id(self):
            tabwidget_from = str(mimeData.data("tabwidget-id").toLong()[0])
            
            # We pass self object ID as a QString, because otherwise it would 
            # depend on the platform: long for 64bit, int for 32bit. Replacing 
            # by long all the time is not working on some 32bit platforms 
            # (see Issue 1094, Issue 1098)
            self.emit(SIGNAL("move_tab(QString,int,int)"), 
                      tabwidget_from, index_from, index_to)

            event.acceptProposedAction()
        elif index_from != index_to:
            self.emit(SIGNAL("move_tab(int,int)"), index_from, index_to)
            event.acceptProposedAction()
        QTabBar.dropEvent(self, event)
Example #20
0
    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
Example #21
0
 def _setupUi(self):
     self.setWindowTitle(tr("Import"))
     self.resize(557, 407)
     self.verticalLayout = QtGui.QVBoxLayout(self)
     self.tabView = QTabBar(self)
     self.tabView.setMinimumSize(QtCore.QSize(0, 20))
     self.verticalLayout.addWidget(self.tabView)
     self.targetAccountLayout = QtGui.QHBoxLayout()
     self.targetAccountLabel = QtGui.QLabel(tr("Target Account:"))
     self.targetAccountLayout.addWidget(self.targetAccountLabel)
     self.targetAccountComboBox = QComboBox(self)
     self.targetAccountComboBox.setMinimumSize(QtCore.QSize(150, 0))
     self.targetAccountLayout.addWidget(self.targetAccountComboBox)
     spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
     self.targetAccountLayout.addItem(spacerItem)
     self.groupBox = QGroupBox(tr("Are some fields wrong? Fix them!"))
     self.gridLayout = QtGui.QGridLayout(self.groupBox)
     self.swapOptionsComboBoxView = QComboBox(self.groupBox)
     self.gridLayout.addWidget(self.swapOptionsComboBoxView, 0, 0, 1, 2)
     self.applyToAllCheckBox = QtGui.QCheckBox(tr("Apply to all accounts"))
     self.gridLayout.addWidget(self.applyToAllCheckBox, 1, 0, 1, 1)
     self.swapButton = QPushButton(tr("Fix"))
     self.gridLayout.addWidget(self.swapButton, 1, 1, 1, 1)
     self.targetAccountLayout.addWidget(self.groupBox)
     self.verticalLayout.addLayout(self.targetAccountLayout)
     self.tableView = TableView(self)
     self.tableView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
     self.tableView.setDragEnabled(True)
     self.tableView.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
     self.tableView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
     self.tableView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
     self.tableView.horizontalHeader().setHighlightSections(False)
     self.tableView.horizontalHeader().setMinimumSectionSize(18)
     self.tableView.verticalHeader().setVisible(False)
     self.tableView.verticalHeader().setDefaultSectionSize(18)
     self.verticalLayout.addWidget(self.tableView)
     self.horizontalLayout = QtGui.QHBoxLayout()
     spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
     self.horizontalLayout.addItem(spacerItem1)
     self.importButton = QPushButton(tr("Import"))
     self.horizontalLayout.addWidget(self.importButton)
     self.verticalLayout.addLayout(self.horizontalLayout)
     self.tabView.setTabsClosable(True)
     self.tabView.setDrawBase(False)
     self.tabView.setDocumentMode(True)
     self.tabView.setUsesScrollButtons(True)
Example #22
0
    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
Example #23
0
 def addWidgets(self):
     """Create main layout."""
     logger = self.logger
     logger.debug('adding widgets')
     layout = QVBoxLayout()
     self.setLayout(layout)
     layout.setSpacing(0)
     layout.setContentsMargins(0, 0, 0, 0)
     tabbar = QTabBar(self)
     tabbar.setFocusPolicy(Qt.NoFocus)
     tabbar.setVisible(False)
     tabbar.currentChanged.connect(self.changeVault)
     layout.addWidget(tabbar)
     self.tabbar = tabbar
     stack = QStackedWidget(self)
     layout.addWidget(stack)
     novault = NoVaultWidget(stack)
     stack.addWidget(novault)
     self.stack = stack
Example #24
0
 def mousePressEvent(self, event):
     """Reimplement Qt method"""
     if event.button() == Qt.LeftButton:
         self.__drag_start_pos = QPoint(event.pos())
     QTabBar.mousePressEvent(self, event)
Example #25
0
 def resizeEvent( self, event ):
     self.lineEdit.hide()
     QTabBar.resizeEvent( self, event )
Example #26
0
 def _setupUi(self): # has to take place *before* base elements creation
     self.setWindowTitle("moneyGuru")
     self.resize(700, 580)
     self.centralwidget = QtGui.QWidget(self)
     self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
     self.verticalLayout.setSpacing(0)
     self.verticalLayout.setMargin(0)
     self.topBar = QtGui.QWidget(self.centralwidget)
     self.horizontalLayout_2 = QHBoxLayout(self.topBar)
     self.horizontalLayout_2.setContentsMargins(2, 0, 2, 0)
     spacerItem = QtGui.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
     self.horizontalLayout_2.addItem(spacerItem)
     self.dateRangeSelectorView = DateRangeSelectorView(self.topBar)
     self.dateRangeSelectorView.setMinimumSize(QSize(220, 0))
     self.horizontalLayout_2.addWidget(self.dateRangeSelectorView)
     spacerItem1 = QtGui.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
     self.horizontalLayout_2.addItem(spacerItem1)
     self.searchLineEdit = SearchEdit(self.topBar)
     self.searchLineEdit.setMaximumSize(QSize(240, 16777215))
     self.horizontalLayout_2.addWidget(self.searchLineEdit)
     self.verticalLayout.addWidget(self.topBar)
     self.tabBar = QTabBar(self.centralwidget)
     self.tabBar.setMinimumSize(QSize(0, 20))
     self.verticalLayout.addWidget(self.tabBar)
     self.mainView = QtGui.QStackedWidget(self.centralwidget)
     self.verticalLayout.addWidget(self.mainView)
     
     # Bottom buttons & status label
     self.bottomBar = QtGui.QWidget(self.centralwidget)
     self.horizontalLayout = QHBoxLayout(self.bottomBar)
     self.horizontalLayout.setMargin(2)
     self.horizontalLayout.setMargin(0)
     self.newItemButton = QPushButton(self.bottomBar)
     buttonSizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
     buttonSizePolicy.setHorizontalStretch(0)
     buttonSizePolicy.setVerticalStretch(0)
     buttonSizePolicy.setHeightForWidth(self.newItemButton.sizePolicy().hasHeightForWidth())
     self.newItemButton.setSizePolicy(buttonSizePolicy)
     self.newItemButton.setIcon(QIcon(QPixmap(':/plus_8')))
     self.horizontalLayout.addWidget(self.newItemButton)
     self.deleteItemButton = QPushButton(self.bottomBar)
     self.deleteItemButton.setSizePolicy(buttonSizePolicy)
     self.deleteItemButton.setIcon(QIcon(QPixmap(':/minus_8')))
     self.horizontalLayout.addWidget(self.deleteItemButton)
     self.editItemButton = QPushButton(self.bottomBar)
     self.editItemButton.setSizePolicy(buttonSizePolicy)
     self.editItemButton.setIcon(QIcon(QPixmap(':/info_gray_12')))
     self.horizontalLayout.addWidget(self.editItemButton)
     self.horizontalLayout.addItem(horizontalSpacer(size=20))
     self.graphVisibilityButton = QPushButton()
     self.graphVisibilityButton.setSizePolicy(buttonSizePolicy)
     self.graphVisibilityButton.setIcon(QIcon(QPixmap(':/graph_visibility_on_16')))
     self.horizontalLayout.addWidget(self.graphVisibilityButton)
     self.piechartVisibilityButton = QPushButton()
     self.piechartVisibilityButton.setSizePolicy(buttonSizePolicy)
     self.piechartVisibilityButton.setIcon(QIcon(QPixmap(':/piechart_visibility_on_16')))
     self.horizontalLayout.addWidget(self.piechartVisibilityButton)
     self.columnsVisibilityButton = QPushButton()
     self.columnsVisibilityButton.setSizePolicy(buttonSizePolicy)
     self.columnsVisibilityButton.setIcon(QIcon(QPixmap(':/columns_16')))
     self.horizontalLayout.addWidget(self.columnsVisibilityButton)
     
     self.statusLabel = QtGui.QLabel(tr("Status"))
     self.statusLabel.setAlignment(Qt.AlignCenter)
     self.horizontalLayout.addWidget(self.statusLabel)
     self.verticalLayout.addWidget(self.bottomBar)
     
     
     self.setCentralWidget(self.centralwidget)
     self.menubar = QMenuBar(self)
     self.menubar.setGeometry(QRect(0, 0, 700, 20))
     self.menuFile = QMenu(tr("File"))
     self.menuOpenRecent = QMenu(tr("Open Recent"))
     self.menuView = QMenu(tr("View"))
     self.menuDateRange = QMenu(tr("Date Range"))
     self.menuEdit = QMenu(tr("Edit"))
     self.menuHelp = QMenu(tr("Help"))
     self.setMenuBar(self.menubar)
     self.actionOpenDocument = QAction(tr("Open..."), self)
     self.actionOpenDocument.setShortcut("Ctrl+O")
     self.actionShowNetWorth = QAction(tr("Net Worth"), self)
     self.actionShowNetWorth.setShortcut("Ctrl+1")
     self.actionShowNetWorth.setIcon(QIcon(QPixmap(':/balance_sheet_48')))
     self.actionShowProfitLoss = QAction(escapeamp(tr("Profit & Loss")), self)
     self.actionShowProfitLoss.setShortcut("Ctrl+2")
     self.actionShowProfitLoss.setIcon(QIcon(QPixmap(':/income_statement_48')))
     self.actionShowTransactions = QAction(tr("Transactions"), self)
     self.actionShowTransactions.setShortcut("Ctrl+3")
     self.actionShowTransactions.setIcon(QIcon(QPixmap(':/transaction_table_48')))
     self.actionShowSelectedAccount = QAction(tr("Show Account"), self)
     self.actionShowSelectedAccount.setShortcut("Ctrl+]")
     self.actionNewItem = QAction(tr("New Item"), self)
     self.actionNewItem.setShortcut("Ctrl+N")
     self.actionDeleteItem = QAction(tr("Remove Selected"), self)
     self.actionEditItem = QAction(tr("Show Info"), self)
     self.actionEditItem.setShortcut("Ctrl+I")
     self.actionToggleGraph = QAction(tr("Toggle Graph"), self)
     self.actionToggleGraph.setShortcut("Ctrl+Alt+G")
     self.actionTogglePieChart = QAction(tr("Toggle Pie Chart"), self)
     self.actionTogglePieChart.setShortcut("Ctrl+Alt+P")
     self.actionMoveUp = QAction(tr("Move Up"), self)
     self.actionMoveUp.setShortcut("Ctrl++")
     self.actionMoveDown = QAction(tr("Move Down"), self)
     self.actionMoveDown.setShortcut("Ctrl+-")
     self.actionNavigateBack = QAction(tr("Go Back"), self)
     self.actionNavigateBack.setShortcut("Ctrl+[")
     self.actionNewAccountGroup = QAction(tr("New Account Group"), self)
     self.actionNewAccountGroup.setShortcut("Ctrl+Shift+N")
     self.actionShowNextView = QAction(tr("Next View"), self)
     self.actionShowNextView.setShortcut("Ctrl+Shift+]")
     self.actionShowPreviousView = QAction(tr("Previous View"), self)
     self.actionShowPreviousView.setShortcut("Ctrl+Shift+[")
     self.actionNewDocument = QAction(tr("New Document"), self)
     self.actionOpenExampleDocument = QAction(tr("Open Example Document"), self)
     self.actionOpenPluginFolder = QAction(tr("Open Plugin Folder"), self)
     self.actionImport = QAction(tr("Import..."), self)
     self.actionImport.setShortcut("Ctrl+Alt+I")
     self.actionExport = QAction(tr("Export..."), self)
     self.actionExport.setShortcut("Ctrl+Alt+E")
     self.actionSave = QAction(tr("Save"), self)
     self.actionSave.setShortcut("Ctrl+S")
     self.actionSaveAs = QAction(tr("Save As..."), self)
     self.actionSaveAs.setShortcut("Ctrl+Shift+S")
     self.actionAbout = QAction(tr("About moneyGuru"), self)
     self.actionToggleReconciliationMode = QAction(tr("Toggle Reconciliation Mode"), self)
     self.actionToggleReconciliationMode.setShortcut("Ctrl+Shift+R")
     self.actionToggleAccountExclusion = QAction(tr("Toggle Exclusion Status of Account"), self)
     self.actionToggleAccountExclusion.setShortcut("Ctrl+Shift+X")
     self.actionShowSchedules = QAction(tr("Schedules"), self)
     self.actionShowSchedules.setShortcut("Ctrl+4")
     self.actionShowSchedules.setIcon(QIcon(QPixmap(':/schedules_48')))
     self.actionShowBudgets = QAction(tr("Budgets"), self)
     self.actionShowBudgets.setShortcut("Ctrl+5")
     self.actionShowBudgets.setIcon(QIcon(QPixmap(':/budget_48')))
     self.actionReconcileSelected = QAction(tr("Reconcile Selection"), self)
     self.actionReconcileSelected.setShortcut("Ctrl+R")
     self.actionMakeScheduleFromSelected = QAction(tr("Make Schedule from Selected"), self)
     self.actionMakeScheduleFromSelected.setShortcut("Ctrl+M")
     self.actionShowPreferences = QAction(tr("Preferences..."), self)
     self.actionPrint = QAction(tr("Print..."), self)
     self.actionPrint.setShortcut("Ctrl+P")
     self.actionQuit = QAction(tr("Quit moneyGuru"), self)
     self.actionQuit.setShortcut("Ctrl+Q")
     self.actionUndo = QAction(tr("Undo"), self)
     self.actionUndo.setShortcut("Ctrl+Z")
     self.actionRedo = QAction(tr("Redo"), self)
     self.actionRedo.setShortcut("Ctrl+Y")
     self.actionShowHelp = QAction(tr("moneyGuru Help"), self)
     self.actionShowHelp.setShortcut("F1")
     self.actionCheckForUpdate = QAction(tr("Check for update"), self)
     self.actionOpenDebugLog = QAction(tr("Open Debug Log"), self)
     self.actionDuplicateTransaction = QAction(tr("Duplicate Transaction"), self)
     self.actionDuplicateTransaction.setShortcut("Ctrl+D")
     self.actionJumpToAccount = QAction(tr("Jump to Account..."), self)
     self.actionJumpToAccount.setShortcut("Ctrl+Shift+A")
     self.actionNewTab = QAction(tr("New Tab"), self)
     self.actionNewTab.setShortcut("Ctrl+T")
     self.actionCloseTab = QAction(tr("Close Tab"), self)
     self.actionCloseTab.setShortcut("Ctrl+W")
     
     self.menuFile.addAction(self.actionNewDocument)
     self.menuFile.addAction(self.actionNewTab)
     self.menuFile.addAction(self.actionOpenDocument)
     self.menuFile.addAction(self.menuOpenRecent.menuAction())
     self.menuFile.addAction(self.actionOpenExampleDocument)
     self.menuFile.addAction(self.actionOpenPluginFolder)
     self.menuFile.addAction(self.actionImport)
     self.menuFile.addSeparator()
     self.menuFile.addAction(self.actionCloseTab)
     self.menuFile.addAction(self.actionSave)
     self.menuFile.addAction(self.actionSaveAs)
     self.menuFile.addAction(self.actionExport)
     self.menuFile.addAction(self.actionPrint)
     self.menuFile.addAction(self.actionQuit)
     self.menuView.addAction(self.actionShowNetWorth)
     self.menuView.addAction(self.actionShowProfitLoss)
     self.menuView.addAction(self.actionShowTransactions)
     self.menuView.addAction(self.actionShowSchedules)
     self.menuView.addAction(self.actionShowBudgets)
     self.menuView.addAction(self.actionShowPreviousView)
     self.menuView.addAction(self.actionShowNextView)
     self.menuView.addAction(self.menuDateRange.menuAction())
     self.menuView.addAction(self.actionShowPreferences)
     self.menuView.addAction(self.actionToggleGraph)
     self.menuView.addAction(self.actionTogglePieChart)
     self.menuEdit.addAction(self.actionNewItem)
     self.menuEdit.addAction(self.actionNewAccountGroup)
     self.menuEdit.addAction(self.actionDeleteItem)
     self.menuEdit.addAction(self.actionEditItem)
     self.menuEdit.addSeparator()
     self.menuEdit.addAction(self.actionMoveUp)
     self.menuEdit.addAction(self.actionMoveDown)
     self.menuEdit.addAction(self.actionDuplicateTransaction)
     self.menuEdit.addAction(self.actionMakeScheduleFromSelected)
     self.menuEdit.addAction(self.actionReconcileSelected)
     self.menuEdit.addAction(self.actionToggleReconciliationMode)
     self.menuEdit.addAction(self.actionToggleAccountExclusion)
     self.menuEdit.addSeparator()
     self.menuEdit.addAction(self.actionShowSelectedAccount)
     self.menuEdit.addAction(self.actionNavigateBack)
     self.menuEdit.addAction(self.actionJumpToAccount)
     self.menuEdit.addSeparator()
     self.menuEdit.addAction(self.actionUndo)
     self.menuEdit.addAction(self.actionRedo)
     self.menuHelp.addAction(self.actionShowHelp)
     self.menuHelp.addAction(self.actionCheckForUpdate)
     self.menuHelp.addAction(self.actionOpenDebugLog)
     self.menuHelp.addAction(self.actionAbout)
     mainmenus = [self.menuFile, self.menuEdit, self.menuView, self.menuHelp]
     for menu in mainmenus:
         self.menubar.addAction(menu.menuAction())
         setAccelKeys(menu)
     setAccelKeys(self.menubar)
     self.tabBar.setMovable(True)
     self.tabBar.setTabsClosable(True)
     
     seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Right)
     self._shortcutNextTab = QShortcut(seq, self)
     seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Left)
     self._shortcutPrevTab = QShortcut(seq, self)
     
     # Linux setup
     if ISLINUX:
         self.actionCheckForUpdate.setVisible(False) # This only works on Windows
Example #27
0
 def __init__(self):
     QTabBar.__init__(self)
     self.tabTimer = QTimer()
     self.connect(self.tabTimer, SIGNAL('timeout()'), self.__selectTab)
     self.setAcceptDrops(True)
Example #28
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)
    def __init__(self, parent, controller):
        # create window
        QMainWindow.__init__(self)

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle("Tracking Analysis")
        self.setGeometry(100, 200, 10, 10)

        # set controller
        self.controller = controller

        # create main widget & layout
        self.main_widget = QWidget(self)
        self.main_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.main_layout = QGridLayout(self.main_widget)

        # create left widget & layout
        self.left_widget = QWidget(self)
        self.main_layout.addWidget(self.left_widget, 0, 0)

        self.left_layout = QVBoxLayout(self.left_widget)
        self.left_layout.setAlignment(Qt.AlignTop)

        # create list of tracking items
        self.tracking_list_items = []
        self.tracking_list = QListWidget(self)
        self.tracking_list.currentRowChanged.connect(self.controller.switch_tracking_file)
        self.left_layout.addWidget(self.tracking_list)

        # create tracking list buttons
        self.tracking_list_buttons = QHBoxLayout(self)
        self.left_layout.addLayout(self.tracking_list_buttons)

        self.add_tracking_button = QPushButton('+')
        self.add_tracking_button.clicked.connect(self.controller.select_and_open_tracking_files)
        self.add_tracking_button.setToolTip("Add tracking file.")
        self.tracking_list_buttons.addWidget(self.add_tracking_button)

        self.remove_tracking_button = QPushButton('-')
        self.remove_tracking_button.clicked.connect(self.controller.remove_tracking_file)
        self.remove_tracking_button.setToolTip("Remove selected tracking file.")
        self.tracking_list_buttons.addWidget(self.remove_tracking_button)

        self.prev_tracking_button = QPushButton('<')
        self.prev_tracking_button.clicked.connect(self.controller.prev_tracking_file)
        self.prev_tracking_button.setToolTip("Switch to previous tracking file.")
        self.tracking_list_buttons.addWidget(self.prev_tracking_button)

        self.next_tracking_button = QPushButton('>')
        self.next_tracking_button.clicked.connect(self.controller.next_tracking_file)
        self.next_tracking_button.setToolTip("Switch to next tracking file.")
        self.tracking_list_buttons.addWidget(self.next_tracking_button)

        # create right widget & layout
        self.right_widget = QWidget(self)
        self.right_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.main_layout.addWidget(self.right_widget, 0, 1)
        
        self.right_layout = QVBoxLayout(self.right_widget)
        self.right_layout.setAlignment(Qt.AlignTop)
        self.right_layout.setSpacing(5)

        # create button layout for main widget
        plot_horiz_layout = QHBoxLayout()
        self.right_layout.addLayout(plot_horiz_layout)

        # add param labels & textboxes
        plot_type_label = QLabel()
        plot_type_label.setText("Plot:")
        plot_horiz_layout.addWidget(plot_type_label)
        plot_horiz_layout.addStretch(1)

        # create tab widget for plot type
        self.plot_tabs_widget = QTabBar()
        self.plot_tabs_widget.setDrawBase(False)
        self.plot_tabs_widget.setExpanding(False)
        self.plot_tabs_widget.currentChanged.connect(self.controller.change_plot_type)
        plot_horiz_layout.addWidget(self.plot_tabs_widget)

        # create button layout for main widget
        crop_horiz_layout = QHBoxLayout()
        self.right_layout.addLayout(crop_horiz_layout)

        # add param labels & textboxes
        crop_type_label = QLabel()
        crop_type_label.setText("Crop #:")
        crop_horiz_layout.addWidget(crop_type_label)
        crop_horiz_layout.addStretch(1)

        # create tab widget for crop number
        self.crop_tabs_widget = QTabBar()
        self.crop_tabs_widget.setDrawBase(False)
        self.crop_tabs_widget.setExpanding(False)
        self.crop_tabs_widget.currentChanged.connect(self.controller.change_crop)
        crop_horiz_layout.addWidget(self.crop_tabs_widget)

        # create button layout for main widget
        button_layout = QHBoxLayout()
        button_layout.addStretch(1)
        self.right_layout.addLayout(button_layout)

        # add buttons
        self.show_tracking_params_button = QPushButton('Tracking Parameters', self)
        self.show_tracking_params_button.setMinimumHeight(30)
        self.show_tracking_params_button.clicked.connect(self.controller.show_tracking_params)
        button_layout.addWidget(self.show_tracking_params_button)

        # create stacked widget & layout
        self.stacked_widget = QStackedWidget(self)
        self.stacked_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.right_layout.addWidget(self.stacked_widget)

        self.create_tail_tracking_widget(self.stacked_widget)
        self.create_body_tracking_widget(self.stacked_widget)

        # self.right_layout = QVBoxLayout(self.right_widget)
        # self.right_layout.setAlignment(Qt.AlignTop)
        # self.right_layout.setSpacing(5)

        # self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

        # set window titlebar buttons
        self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint)

        self.show()
Example #30
0
 def mousePressEvent( self, event ):
     self.lineEdit.hide()
     QTabBar.mousePressEvent( self, event )
Example #31
0
class MainWindow(QMainWindow):
    def __init__(self, doc):
        QMainWindow.__init__(self, None)
        self.doc = doc
        self.app = doc.app
        
        self._setupUi()
        
        # Create base elements
        self.model = MainWindowModel(document=doc.model)
        self.model2view = {}
        self.apanel = AccountPanel(mainwindow=self)
        self.tpanel = TransactionPanel(mainwindow=self)
        self.mepanel = MassEditionPanel(mainwindow=self)
        self.scpanel = SchedulePanel(mainwindow=self)
        self.bpanel = BudgetPanel(mainwindow=self)
        self.cdrpanel = CustomDateRangePanel(mainwindow=self)
        self.arpanel = AccountReassignPanel(mainwindow=self)
        self.expanel = ExportPanel(mainwindow=self)
        self.alookup = Lookup(self, model=self.model.account_lookup)
        self.clookup = Lookup(self, model=self.model.completion_lookup)
        self.drsel = DateRangeSelector(mainwindow=self, view=self.dateRangeSelectorView)
        self.sfield = SearchField(model=self.model.search_field, view=self.searchLineEdit)
        self.recentDocuments = Recent(self.app, 'recentDocuments')
        self.recentDocuments.addMenu(self.menuOpenRecent)
        
        self.model.view = self
        self.model.connect()
        
        self._updateUndoActions()
        self._bindSignals()
    
    def _setupUi(self): # has to take place *before* base elements creation
        self.setWindowTitle("moneyGuru")
        self.resize(700, 580)
        self.centralwidget = QtGui.QWidget(self)
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setMargin(0)
        self.topBar = QtGui.QWidget(self.centralwidget)
        self.horizontalLayout_2 = QHBoxLayout(self.topBar)
        self.horizontalLayout_2.setContentsMargins(2, 0, 2, 0)
        spacerItem = QtGui.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.dateRangeSelectorView = DateRangeSelectorView(self.topBar)
        self.dateRangeSelectorView.setMinimumSize(QSize(220, 0))
        self.horizontalLayout_2.addWidget(self.dateRangeSelectorView)
        spacerItem1 = QtGui.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem1)
        self.searchLineEdit = SearchEdit(self.topBar)
        self.searchLineEdit.setMaximumSize(QSize(240, 16777215))
        self.horizontalLayout_2.addWidget(self.searchLineEdit)
        self.verticalLayout.addWidget(self.topBar)
        self.tabBar = QTabBar(self.centralwidget)
        self.tabBar.setMinimumSize(QSize(0, 20))
        self.verticalLayout.addWidget(self.tabBar)
        self.mainView = QtGui.QStackedWidget(self.centralwidget)
        self.verticalLayout.addWidget(self.mainView)
        
        # Bottom buttons & status label
        self.bottomBar = QtGui.QWidget(self.centralwidget)
        self.horizontalLayout = QHBoxLayout(self.bottomBar)
        self.horizontalLayout.setMargin(2)
        self.horizontalLayout.setMargin(0)
        self.newItemButton = QPushButton(self.bottomBar)
        buttonSizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        buttonSizePolicy.setHorizontalStretch(0)
        buttonSizePolicy.setVerticalStretch(0)
        buttonSizePolicy.setHeightForWidth(self.newItemButton.sizePolicy().hasHeightForWidth())
        self.newItemButton.setSizePolicy(buttonSizePolicy)
        self.newItemButton.setIcon(QIcon(QPixmap(':/plus_8')))
        self.horizontalLayout.addWidget(self.newItemButton)
        self.deleteItemButton = QPushButton(self.bottomBar)
        self.deleteItemButton.setSizePolicy(buttonSizePolicy)
        self.deleteItemButton.setIcon(QIcon(QPixmap(':/minus_8')))
        self.horizontalLayout.addWidget(self.deleteItemButton)
        self.editItemButton = QPushButton(self.bottomBar)
        self.editItemButton.setSizePolicy(buttonSizePolicy)
        self.editItemButton.setIcon(QIcon(QPixmap(':/info_gray_12')))
        self.horizontalLayout.addWidget(self.editItemButton)
        self.horizontalLayout.addItem(horizontalSpacer(size=20))
        self.graphVisibilityButton = QPushButton()
        self.graphVisibilityButton.setSizePolicy(buttonSizePolicy)
        self.graphVisibilityButton.setIcon(QIcon(QPixmap(':/graph_visibility_on_16')))
        self.horizontalLayout.addWidget(self.graphVisibilityButton)
        self.piechartVisibilityButton = QPushButton()
        self.piechartVisibilityButton.setSizePolicy(buttonSizePolicy)
        self.piechartVisibilityButton.setIcon(QIcon(QPixmap(':/piechart_visibility_on_16')))
        self.horizontalLayout.addWidget(self.piechartVisibilityButton)
        self.columnsVisibilityButton = QPushButton()
        self.columnsVisibilityButton.setSizePolicy(buttonSizePolicy)
        self.columnsVisibilityButton.setIcon(QIcon(QPixmap(':/columns_16')))
        self.horizontalLayout.addWidget(self.columnsVisibilityButton)
        
        self.statusLabel = QtGui.QLabel(tr("Status"))
        self.statusLabel.setAlignment(Qt.AlignCenter)
        self.horizontalLayout.addWidget(self.statusLabel)
        self.verticalLayout.addWidget(self.bottomBar)
        
        
        self.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 700, 20))
        self.menuFile = QMenu(tr("File"))
        self.menuOpenRecent = QMenu(tr("Open Recent"))
        self.menuView = QMenu(tr("View"))
        self.menuDateRange = QMenu(tr("Date Range"))
        self.menuEdit = QMenu(tr("Edit"))
        self.menuHelp = QMenu(tr("Help"))
        self.setMenuBar(self.menubar)
        self.actionOpenDocument = QAction(tr("Open..."), self)
        self.actionOpenDocument.setShortcut("Ctrl+O")
        self.actionShowNetWorth = QAction(tr("Net Worth"), self)
        self.actionShowNetWorth.setShortcut("Ctrl+1")
        self.actionShowNetWorth.setIcon(QIcon(QPixmap(':/balance_sheet_48')))
        self.actionShowProfitLoss = QAction(escapeamp(tr("Profit & Loss")), self)
        self.actionShowProfitLoss.setShortcut("Ctrl+2")
        self.actionShowProfitLoss.setIcon(QIcon(QPixmap(':/income_statement_48')))
        self.actionShowTransactions = QAction(tr("Transactions"), self)
        self.actionShowTransactions.setShortcut("Ctrl+3")
        self.actionShowTransactions.setIcon(QIcon(QPixmap(':/transaction_table_48')))
        self.actionShowSelectedAccount = QAction(tr("Show Account"), self)
        self.actionShowSelectedAccount.setShortcut("Ctrl+]")
        self.actionNewItem = QAction(tr("New Item"), self)
        self.actionNewItem.setShortcut("Ctrl+N")
        self.actionDeleteItem = QAction(tr("Remove Selected"), self)
        self.actionEditItem = QAction(tr("Show Info"), self)
        self.actionEditItem.setShortcut("Ctrl+I")
        self.actionToggleGraph = QAction(tr("Toggle Graph"), self)
        self.actionToggleGraph.setShortcut("Ctrl+Alt+G")
        self.actionTogglePieChart = QAction(tr("Toggle Pie Chart"), self)
        self.actionTogglePieChart.setShortcut("Ctrl+Alt+P")
        self.actionMoveUp = QAction(tr("Move Up"), self)
        self.actionMoveUp.setShortcut("Ctrl++")
        self.actionMoveDown = QAction(tr("Move Down"), self)
        self.actionMoveDown.setShortcut("Ctrl+-")
        self.actionNavigateBack = QAction(tr("Go Back"), self)
        self.actionNavigateBack.setShortcut("Ctrl+[")
        self.actionNewAccountGroup = QAction(tr("New Account Group"), self)
        self.actionNewAccountGroup.setShortcut("Ctrl+Shift+N")
        self.actionShowNextView = QAction(tr("Next View"), self)
        self.actionShowNextView.setShortcut("Ctrl+Shift+]")
        self.actionShowPreviousView = QAction(tr("Previous View"), self)
        self.actionShowPreviousView.setShortcut("Ctrl+Shift+[")
        self.actionNewDocument = QAction(tr("New Document"), self)
        self.actionOpenExampleDocument = QAction(tr("Open Example Document"), self)
        self.actionOpenPluginFolder = QAction(tr("Open Plugin Folder"), self)
        self.actionImport = QAction(tr("Import..."), self)
        self.actionImport.setShortcut("Ctrl+Alt+I")
        self.actionExport = QAction(tr("Export..."), self)
        self.actionExport.setShortcut("Ctrl+Alt+E")
        self.actionSave = QAction(tr("Save"), self)
        self.actionSave.setShortcut("Ctrl+S")
        self.actionSaveAs = QAction(tr("Save As..."), self)
        self.actionSaveAs.setShortcut("Ctrl+Shift+S")
        self.actionAbout = QAction(tr("About moneyGuru"), self)
        self.actionToggleReconciliationMode = QAction(tr("Toggle Reconciliation Mode"), self)
        self.actionToggleReconciliationMode.setShortcut("Ctrl+Shift+R")
        self.actionToggleAccountExclusion = QAction(tr("Toggle Exclusion Status of Account"), self)
        self.actionToggleAccountExclusion.setShortcut("Ctrl+Shift+X")
        self.actionShowSchedules = QAction(tr("Schedules"), self)
        self.actionShowSchedules.setShortcut("Ctrl+4")
        self.actionShowSchedules.setIcon(QIcon(QPixmap(':/schedules_48')))
        self.actionShowBudgets = QAction(tr("Budgets"), self)
        self.actionShowBudgets.setShortcut("Ctrl+5")
        self.actionShowBudgets.setIcon(QIcon(QPixmap(':/budget_48')))
        self.actionReconcileSelected = QAction(tr("Reconcile Selection"), self)
        self.actionReconcileSelected.setShortcut("Ctrl+R")
        self.actionMakeScheduleFromSelected = QAction(tr("Make Schedule from Selected"), self)
        self.actionMakeScheduleFromSelected.setShortcut("Ctrl+M")
        self.actionShowPreferences = QAction(tr("Preferences..."), self)
        self.actionPrint = QAction(tr("Print..."), self)
        self.actionPrint.setShortcut("Ctrl+P")
        self.actionQuit = QAction(tr("Quit moneyGuru"), self)
        self.actionQuit.setShortcut("Ctrl+Q")
        self.actionUndo = QAction(tr("Undo"), self)
        self.actionUndo.setShortcut("Ctrl+Z")
        self.actionRedo = QAction(tr("Redo"), self)
        self.actionRedo.setShortcut("Ctrl+Y")
        self.actionShowHelp = QAction(tr("moneyGuru Help"), self)
        self.actionShowHelp.setShortcut("F1")
        self.actionCheckForUpdate = QAction(tr("Check for update"), self)
        self.actionOpenDebugLog = QAction(tr("Open Debug Log"), self)
        self.actionDuplicateTransaction = QAction(tr("Duplicate Transaction"), self)
        self.actionDuplicateTransaction.setShortcut("Ctrl+D")
        self.actionJumpToAccount = QAction(tr("Jump to Account..."), self)
        self.actionJumpToAccount.setShortcut("Ctrl+Shift+A")
        self.actionNewTab = QAction(tr("New Tab"), self)
        self.actionNewTab.setShortcut("Ctrl+T")
        self.actionCloseTab = QAction(tr("Close Tab"), self)
        self.actionCloseTab.setShortcut("Ctrl+W")
        
        self.menuFile.addAction(self.actionNewDocument)
        self.menuFile.addAction(self.actionNewTab)
        self.menuFile.addAction(self.actionOpenDocument)
        self.menuFile.addAction(self.menuOpenRecent.menuAction())
        self.menuFile.addAction(self.actionOpenExampleDocument)
        self.menuFile.addAction(self.actionOpenPluginFolder)
        self.menuFile.addAction(self.actionImport)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.actionCloseTab)
        self.menuFile.addAction(self.actionSave)
        self.menuFile.addAction(self.actionSaveAs)
        self.menuFile.addAction(self.actionExport)
        self.menuFile.addAction(self.actionPrint)
        self.menuFile.addAction(self.actionQuit)
        self.menuView.addAction(self.actionShowNetWorth)
        self.menuView.addAction(self.actionShowProfitLoss)
        self.menuView.addAction(self.actionShowTransactions)
        self.menuView.addAction(self.actionShowSchedules)
        self.menuView.addAction(self.actionShowBudgets)
        self.menuView.addAction(self.actionShowPreviousView)
        self.menuView.addAction(self.actionShowNextView)
        self.menuView.addAction(self.menuDateRange.menuAction())
        self.menuView.addAction(self.actionShowPreferences)
        self.menuView.addAction(self.actionToggleGraph)
        self.menuView.addAction(self.actionTogglePieChart)
        self.menuEdit.addAction(self.actionNewItem)
        self.menuEdit.addAction(self.actionNewAccountGroup)
        self.menuEdit.addAction(self.actionDeleteItem)
        self.menuEdit.addAction(self.actionEditItem)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionMoveUp)
        self.menuEdit.addAction(self.actionMoveDown)
        self.menuEdit.addAction(self.actionDuplicateTransaction)
        self.menuEdit.addAction(self.actionMakeScheduleFromSelected)
        self.menuEdit.addAction(self.actionReconcileSelected)
        self.menuEdit.addAction(self.actionToggleReconciliationMode)
        self.menuEdit.addAction(self.actionToggleAccountExclusion)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionShowSelectedAccount)
        self.menuEdit.addAction(self.actionNavigateBack)
        self.menuEdit.addAction(self.actionJumpToAccount)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionUndo)
        self.menuEdit.addAction(self.actionRedo)
        self.menuHelp.addAction(self.actionShowHelp)
        self.menuHelp.addAction(self.actionCheckForUpdate)
        self.menuHelp.addAction(self.actionOpenDebugLog)
        self.menuHelp.addAction(self.actionAbout)
        mainmenus = [self.menuFile, self.menuEdit, self.menuView, self.menuHelp]
        for menu in mainmenus:
            self.menubar.addAction(menu.menuAction())
            setAccelKeys(menu)
        setAccelKeys(self.menubar)
        self.tabBar.setMovable(True)
        self.tabBar.setTabsClosable(True)
        
        seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Right)
        self._shortcutNextTab = QShortcut(seq, self)
        seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Left)
        self._shortcutPrevTab = QShortcut(seq, self)
        
        # Linux setup
        if ISLINUX:
            self.actionCheckForUpdate.setVisible(False) # This only works on Windows
    
    def _bindSignals(self):
        self.newItemButton.clicked.connect(self.actionNewItem.trigger)
        self.deleteItemButton.clicked.connect(self.actionDeleteItem.trigger)
        self.editItemButton.clicked.connect(self.actionEditItem.trigger)
        self.graphVisibilityButton.clicked.connect(self.actionToggleGraph.trigger)
        self.piechartVisibilityButton.clicked.connect(self.actionTogglePieChart.trigger)
        self.columnsVisibilityButton.clicked.connect(self.columnsVisibilityButtonClicked)
        self.recentDocuments.mustOpenItem.connect(self.doc.open)
        self.doc.documentOpened.connect(self.recentDocuments.insertItem)
        self.doc.documentSavedAs.connect(self.recentDocuments.insertItem)
        self.doc.documentPathChanged.connect(self.documentPathChanged)
        self.tabBar.currentChanged.connect(self.currentTabChanged)
        self.tabBar.tabCloseRequested.connect(self.tabCloseRequested)
        self.tabBar.tabMoved.connect(self.tabMoved)
        
        # Views
        self.actionShowNetWorth.triggered.connect(self.showNetWorthTriggered)        
        self.actionShowProfitLoss.triggered.connect(self.showProfitLossTriggered)        
        self.actionShowTransactions.triggered.connect(self.showTransactionsTriggered)        
        self.actionShowSchedules.triggered.connect(self.showSchedulesTriggered)        
        self.actionShowBudgets.triggered.connect(self.showBudgetsTriggered)        
        self.actionShowPreviousView.triggered.connect(self.showPreviousViewTriggered)        
        self.actionShowNextView.triggered.connect(self.showNextViewTriggered)        
        self.actionShowPreferences.triggered.connect(self.app.showPreferences)
        self.actionToggleGraph.triggered.connect(self.toggleGraphTriggered)
        self.actionTogglePieChart.triggered.connect(self.togglePieChartTriggered)
        
        # Document Edition
        self.actionNewItem.triggered.connect(self.newItemTriggered)
        self.actionNewAccountGroup.triggered.connect(self.newAccountGroupTriggered)
        self.actionDeleteItem.triggered.connect(self.deleteItemTriggered)
        self.actionEditItem.triggered.connect(self.editItemTriggered)
        self.actionMoveUp.triggered.connect(self.moveUpTriggered)
        self.actionMoveDown.triggered.connect(self.moveDownTriggered)
        self.actionDuplicateTransaction.triggered.connect(self.model.duplicate_item)
        self.actionUndo.triggered.connect(self.doc.model.undo)
        self.actionRedo.triggered.connect(self.doc.model.redo)
        
        # Open / Save / Import / Export / New
        self.actionNewDocument.triggered.connect(self.doc.new)
        self.actionOpenDocument.triggered.connect(self.doc.openDocument)
        self.actionOpenExampleDocument.triggered.connect(self.doc.openExampleDocument)
        self.actionOpenPluginFolder.triggered.connect(self.model.app.open_plugin_folder)
        self.actionImport.triggered.connect(self.doc.importDocument)
        self.actionSave.triggered.connect(self.doc.save)
        self.actionSaveAs.triggered.connect(self.doc.saveAs)
        self.actionExport.triggered.connect(self.model.export)
        
        # Misc
        self.actionNewTab.triggered.connect(self.model.new_tab)
        self.actionCloseTab.triggered.connect(self.closeTabTriggered)
        self.actionShowSelectedAccount.triggered.connect(self.model.show_account)
        self.actionNavigateBack.triggered.connect(self.navigateBackTriggered)
        self.actionJumpToAccount.triggered.connect(self.jumpToAccountTriggered)
        self.actionMakeScheduleFromSelected.triggered.connect(self.makeScheduleFromSelectedTriggered)
        self.actionReconcileSelected.triggered.connect(self.reconcileSelectedTriggered)
        self.actionToggleReconciliationMode.triggered.connect(self.toggleReconciliationModeTriggered)
        self.actionToggleAccountExclusion.triggered.connect(self.toggleAccountExclusionTriggered)
        self.actionPrint.triggered.connect(self._print)
        self.actionShowHelp.triggered.connect(self.app.showHelp)
        self.actionCheckForUpdate.triggered.connect(self.checkForUpdateTriggered)
        self.actionAbout.triggered.connect(self.aboutTriggered)
        self.actionOpenDebugLog.triggered.connect(self.openDebugLogTriggered)
        self.actionQuit.triggered.connect(self.close)
        
        # Extra Shortcuts
        self._shortcutNextTab.activated.connect(self.showNextViewTriggered)
        self._shortcutPrevTab.activated.connect(self.showPreviousViewTriggered)
    
    #--- QWidget overrides
    def closeEvent(self, event):
        if self.doc.confirmDestructiveAction():
            event.accept()
        else:
            event.ignore()
    
    #--- Private
    def _print(self):
        dialog = QPrintDialog(self)
        if dialog.exec_() != QPrintDialog.Accepted:
            return
        printer = dialog.printer()
        currentView = self.mainView.currentWidget()
        viewPrinter = ViewPrinter(printer, currentView)
        currentView.fitViewsForPrint(viewPrinter)
        viewPrinter.render()
    
    def _getViewforPane(self, pane_type, pane_view):
        if pane_view in self.model2view:
            view = self.model2view[pane_view]
        else:
            view = PANETYPE2VIEWCLASS[pane_type](model=pane_view)
            self.model2view[pane_view] = view
            self.mainView.addWidget(view)
            view.restoreSubviewsSize()
        return view
    
    def _setTabIndex(self, index):
        if not self.tabBar.count():
            return
        self.tabBar.setCurrentIndex(index)
        self._updateActionsState()
        pane_type = self.model.pane_type(index)
        pane_view = self.model.pane_view(index)
        view = self._getViewforPane(pane_type, pane_view)
        self.mainView.setCurrentWidget(view)
        view.setFocus()
    
    def _activeView(self):
        paneIndex = self.model.current_pane_index
        return self.model.pane_view(paneIndex)
    
    def _updateActionsState(self):
        # Updates enable/disable checked/unchecked state of all actions. These state can change
        # under various conditions: main view change, date range type change and when reconciliation
        # mode is toggled
        
        # Determine what actions are enabled
        view = self._activeView()
        viewType = view.VIEW_TYPE
        isSheet = viewType in {PaneType.NetWorth, PaneType.Profit}
        isTransactionOrEntryTable = viewType in {PaneType.Transaction, PaneType.Account}
        canToggleReconciliation = viewType == PaneType.Account and view.can_toggle_reconciliation_mode
        
        newItemLabel = {
            PaneType.NetWorth: tr("New Account"),
            PaneType.Profit: tr("New Account"),
            PaneType.Transaction: tr("New Transaction"),
            PaneType.Account: tr("New Transaction"),
            PaneType.Schedule: tr("New Schedule"),
            PaneType.Budget: tr("New Budget"),
            PaneType.GeneralLedger: tr("New Transaction"),
        }.get(viewType, tr("New Item")) #XXX make "New Item" disabled
        self.actionNewItem.setText(newItemLabel)
        self.actionNewAccountGroup.setEnabled(isSheet)
        self.actionMoveDown.setEnabled(isTransactionOrEntryTable)
        self.actionMoveUp.setEnabled(isTransactionOrEntryTable)
        self.actionDuplicateTransaction.setEnabled(isTransactionOrEntryTable)
        self.actionMakeScheduleFromSelected.setEnabled(isTransactionOrEntryTable)
        self.actionReconcileSelected.setEnabled(viewType == PaneType.Account and view.reconciliation_mode)
        self.actionShowNextView.setEnabled(self.model.current_pane_index < self.model.pane_count-1)
        self.actionShowPreviousView.setEnabled(self.model.current_pane_index > 0)
        self.actionShowSelectedAccount.setEnabled(isSheet or isTransactionOrEntryTable)
        self.actionNavigateBack.setEnabled(viewType == PaneType.Account)
        self.actionToggleReconciliationMode.setEnabled(canToggleReconciliation)
        self.actionToggleAccountExclusion.setEnabled(isSheet)
    
    def _updateUndoActions(self):
        if self.doc.model.can_undo():
            self.actionUndo.setEnabled(True)
            self.actionUndo.setText(tr("Undo {0}").format(self.doc.model.undo_description()))
        else:
            self.actionUndo.setEnabled(False)
            self.actionUndo.setText(tr("Undo"))
        if self.doc.model.can_redo():
            self.actionRedo.setEnabled(True)
            self.actionRedo.setText(tr("Redo {0}").format(self.doc.model.redo_description()))
        else:
            self.actionRedo.setEnabled(False)
            self.actionRedo.setText(tr("Redo"))
    
    #--- Actions
    # Views
    def showNetWorthTriggered(self):
        self.model.select_pane_of_type(PaneType.NetWorth)
    
    def showProfitLossTriggered(self):
        self.model.select_pane_of_type(PaneType.Profit)
    
    def showTransactionsTriggered(self):
        self.model.select_pane_of_type(PaneType.Transaction)
    
    def showSchedulesTriggered(self):
        self.model.select_pane_of_type(PaneType.Schedule)
    
    def showBudgetsTriggered(self):
        self.model.select_pane_of_type(PaneType.Budget)
    
    def showPreviousViewTriggered(self):
        self.model.select_previous_view()
    
    def showNextViewTriggered(self):
        self.model.select_next_view()
    
    # Document Edition
    def newItemTriggered(self):
        self.model.new_item()
    
    def newAccountGroupTriggered(self):
        self.model.new_group()
    
    def deleteItemTriggered(self):
        self.model.delete_item()
    
    def editItemTriggered(self):
        self.model.edit_item()
    
    def moveUpTriggered(self):
        self.model.move_up()
    
    def moveDownTriggered(self):
        self.model.move_down()
    
    # Misc
    def closeTabTriggered(self):
        self.model.close_pane(self.model.current_pane_index)
    
    def navigateBackTriggered(self):
        self.model.navigate_back()
    
    def jumpToAccountTriggered(self):
        self.model.jump_to_account()
    
    def makeScheduleFromSelectedTriggered(self):
        self.model.make_schedule_from_selected()
    
    def reconcileSelectedTriggered(self):
        self._activeView().etable.toggle_reconciled()
    
    def toggleReconciliationModeTriggered(self):
        self._activeView().toggle_reconciliation_mode()
        self._updateActionsState()
    
    def toggleAccountExclusionTriggered(self):
        viewType = self.model.pane_type(self.model.current_pane_index)
        if viewType in {PaneType.NetWorth, PaneType.Profit}:
            self._activeView().sheet.toggle_excluded()
    
    def toggleGraphTriggered(self):
        self.model.toggle_area_visibility(PaneArea.BottomGraph)
    
    def togglePieChartTriggered(self):
        self.model.toggle_area_visibility(PaneArea.RightChart)
    
    def columnsVisibilityButtonClicked(self):
        items = self.model.column_menu_items()
        if not items:
            return
        menu = QMenu()
        for i, (display, marked) in enumerate(items):
            action = menu.addAction(display)
            action.setCheckable(True)
            action.setChecked(marked)
            action.setData(i)
            action.triggered.connect(self.columnsMenuItemWasClicked)
        self._columnMenuHolder = menu # we need to hold a reference to it while it popups
        button = self.columnsVisibilityButton
        menu.popup(button.parentWidget().mapToGlobal(button.geometry().topLeft()))
    
    def columnsMenuItemWasClicked(self):
        action = self.sender()
        if action is not None:
            index = action.data()
            self.model.toggle_column_menu_item(index)
    
    def checkForUpdateTriggered(self):
        QProcess.execute('updater.exe', ['/checknow'])
    
    def aboutTriggered(self):
        self.app.showAboutBox()
    
    def openDebugLogTriggered(self):
        debugLogPath = op.join(getAppData(), 'debug.log')
        url = QUrl.fromLocalFile(debugLogPath)
        QDesktopServices.openUrl(url)
    
    #--- Other Signals
    def currentTabChanged(self, index):
        self.model.current_pane_index = index
        self._setTabIndex(index)
    
    def documentPathChanged(self):
        if self.doc.documentPath:
            title = "moneyGuru ({})".format(self.doc.documentPath)
        else:
            title = "moneyGuru"
        self.setWindowTitle(title)
    
    def tabCloseRequested(self, index):
        self.model.close_pane(index)
    
    def tabMoved(self, fromIndex, toIndex):
        self.model.move_pane(fromIndex, toIndex)
    
    #--- model --> view
    def change_current_pane(self):
        self._setTabIndex(self.model.current_pane_index)
    
    def refresh_panes(self):
        while self.tabBar.count() < self.model.pane_count:
            self.tabBar.addTab('')
        for i in range(self.model.pane_count):
            pane_label = self.model.pane_label(i)
            pane_label = escapeamp(pane_label)
            self.tabBar.setTabText(i, pane_label)
            pane_type = self.model.pane_type(i)
            pane_view = self.model.pane_view(i)
            # Ensure that the view's "view" has been created and bound
            self._getViewforPane(pane_type, pane_view)
            iconname = PANETYPE2ICON.get(pane_type)
            icon = QIcon(QPixmap(':/{0}'.format(iconname))) if iconname else QIcon()
            self.tabBar.setTabIcon(i, icon)
        # It's important that we proceed with tab removal *after* we've completed tab initialization.
        # We're walking on eggshells here. refresh_panes() can be called in multiple situations, one
        # of them is during the opening of a document. When that happens when another document was
        # previously opened, all views' model are uninitalized and don't have their "view" attribute
        # set yet. If we proceed with the setCurrentIndex() call below before _getViewforPane()
        # could be called above, we get a crash.
        if self.tabBar.currentIndex() < self.model.pane_count:
            # Normally, we don't touch the tabBar index here and wait for change_current_pane,
            # but when we remove tabs, it's possible that currentTabChanged end up being called and
            # then the tab selection is bugged. I tried disconnecting/reconnecting the signal, but
            # this is buggy. So when a selected tab is about to be removed, we change the selection
            # to the model's one immediately.
            self.tabBar.setCurrentIndex(self.model.current_pane_index)
        while self.tabBar.count() > self.model.pane_count:
            self.tabBar.removeTab(self.tabBar.count()-1)
        self.tabBar.setTabsClosable(self.model.pane_count > 1)
    
    def refresh_status_line(self):
        self.statusLabel.setText(self.model.status_line)
    
    def refresh_undo_actions(self):
        self._updateUndoActions()
    
    def restore_window_frame(self, frame):
        self.setGeometry(*frame)
    
    def save_window_frame(self):
        r = self.geometry()
        return (r.x(), r.y(), r.width(), r.height())
    
    def show_message(self, msg):
        title = tr("Warning")
        QMessageBox.warning(self, title, msg)
    
    def update_area_visibility(self):
        hidden = self.model.hidden_areas
        graphimg = ':/graph_visibility_{}_16'.format('off' if PaneArea.BottomGraph in hidden else 'on')
        pieimg = ':/piechart_visibility_{}_16'.format('off' if PaneArea.RightChart in hidden else 'on')
        self.graphVisibilityButton.setIcon(QIcon(QPixmap(graphimg)))
        self.piechartVisibilityButton.setIcon(QIcon(QPixmap(pieimg)))
    
    def view_closed(self, index):
        self.tabBar.removeTab(index)
        self.tabBar.setTabsClosable(self.model.pane_count > 1)
Example #32
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 #33
0
 def mousePressEvent(self, event):
     """Reimplement Qt method"""
     if event.button() == Qt.LeftButton:
         self.__drag_start_pos = QPoint(event.pos())
     QTabBar.mousePressEvent(self, event)
 def leaveEvent(self,event):
     self.hoveredTab = self.currentIndex ()
     self.repaint()
     QTabBar.leaveEvent(self,event)
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)
class AnalysisWindow(QMainWindow):
    def __init__(self, parent, controller):
        # create window
        QMainWindow.__init__(self)

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle("Tracking Analysis")
        self.setGeometry(100, 200, 10, 10)

        # set controller
        self.controller = controller

        # create main widget & layout
        self.main_widget = QWidget(self)
        self.main_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.main_layout = QGridLayout(self.main_widget)

        # create left widget & layout
        self.left_widget = QWidget(self)
        self.main_layout.addWidget(self.left_widget, 0, 0)

        self.left_layout = QVBoxLayout(self.left_widget)
        self.left_layout.setAlignment(Qt.AlignTop)

        # create list of tracking items
        self.tracking_list_items = []
        self.tracking_list = QListWidget(self)
        self.tracking_list.currentRowChanged.connect(self.controller.switch_tracking_file)
        self.left_layout.addWidget(self.tracking_list)

        # create tracking list buttons
        self.tracking_list_buttons = QHBoxLayout(self)
        self.left_layout.addLayout(self.tracking_list_buttons)

        self.add_tracking_button = QPushButton('+')
        self.add_tracking_button.clicked.connect(self.controller.select_and_open_tracking_files)
        self.add_tracking_button.setToolTip("Add tracking file.")
        self.tracking_list_buttons.addWidget(self.add_tracking_button)

        self.remove_tracking_button = QPushButton('-')
        self.remove_tracking_button.clicked.connect(self.controller.remove_tracking_file)
        self.remove_tracking_button.setToolTip("Remove selected tracking file.")
        self.tracking_list_buttons.addWidget(self.remove_tracking_button)

        self.prev_tracking_button = QPushButton('<')
        self.prev_tracking_button.clicked.connect(self.controller.prev_tracking_file)
        self.prev_tracking_button.setToolTip("Switch to previous tracking file.")
        self.tracking_list_buttons.addWidget(self.prev_tracking_button)

        self.next_tracking_button = QPushButton('>')
        self.next_tracking_button.clicked.connect(self.controller.next_tracking_file)
        self.next_tracking_button.setToolTip("Switch to next tracking file.")
        self.tracking_list_buttons.addWidget(self.next_tracking_button)

        # create right widget & layout
        self.right_widget = QWidget(self)
        self.right_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.main_layout.addWidget(self.right_widget, 0, 1)
        
        self.right_layout = QVBoxLayout(self.right_widget)
        self.right_layout.setAlignment(Qt.AlignTop)
        self.right_layout.setSpacing(5)

        # create button layout for main widget
        plot_horiz_layout = QHBoxLayout()
        self.right_layout.addLayout(plot_horiz_layout)

        # add param labels & textboxes
        plot_type_label = QLabel()
        plot_type_label.setText("Plot:")
        plot_horiz_layout.addWidget(plot_type_label)
        plot_horiz_layout.addStretch(1)

        # create tab widget for plot type
        self.plot_tabs_widget = QTabBar()
        self.plot_tabs_widget.setDrawBase(False)
        self.plot_tabs_widget.setExpanding(False)
        self.plot_tabs_widget.currentChanged.connect(self.controller.change_plot_type)
        plot_horiz_layout.addWidget(self.plot_tabs_widget)

        # create button layout for main widget
        crop_horiz_layout = QHBoxLayout()
        self.right_layout.addLayout(crop_horiz_layout)

        # add param labels & textboxes
        crop_type_label = QLabel()
        crop_type_label.setText("Crop #:")
        crop_horiz_layout.addWidget(crop_type_label)
        crop_horiz_layout.addStretch(1)

        # create tab widget for crop number
        self.crop_tabs_widget = QTabBar()
        self.crop_tabs_widget.setDrawBase(False)
        self.crop_tabs_widget.setExpanding(False)
        self.crop_tabs_widget.currentChanged.connect(self.controller.change_crop)
        crop_horiz_layout.addWidget(self.crop_tabs_widget)

        # create button layout for main widget
        button_layout = QHBoxLayout()
        button_layout.addStretch(1)
        self.right_layout.addLayout(button_layout)

        # add buttons
        self.show_tracking_params_button = QPushButton('Tracking Parameters', self)
        self.show_tracking_params_button.setMinimumHeight(30)
        self.show_tracking_params_button.clicked.connect(self.controller.show_tracking_params)
        button_layout.addWidget(self.show_tracking_params_button)

        # create stacked widget & layout
        self.stacked_widget = QStackedWidget(self)
        self.stacked_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.right_layout.addWidget(self.stacked_widget)

        self.create_tail_tracking_widget(self.stacked_widget)
        self.create_body_tracking_widget(self.stacked_widget)

        # self.right_layout = QVBoxLayout(self.right_widget)
        # self.right_layout.setAlignment(Qt.AlignTop)
        # self.right_layout.setSpacing(5)

        # self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)

        # set window titlebar buttons
        self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint)

        self.show()

    def update_plot(self, array, plot_type, extra_tracking=None, keep_xlim=True):
        print("Updating plot")

        if plot_type == "tail":
            self.stacked_widget.setCurrentIndex(0)
            self.plot_window.plot_tail_angle_array(array, extra_tracking=extra_tracking, keep_xlim=keep_xlim)
        elif plot_type == "body":
            self.stacked_widget.setCurrentIndex(1)
            self.plot_window.plot_heading_angle_array(array, keep_xlim=keep_xlim)
        else:
            pass

    def switch_tracking_item(self, row_number):
        print("Switching tracking item")

        tracking_params = self.controller.tracking_params[row_number]

        self.change_selected_tracking_row(row_number)

        self.plot_tabs_widget.blockSignals(True)

        # add plot tabs
        for i in range(self.plot_tabs_widget.count()-1, -1, -1):
            self.plot_tabs_widget.removeTab(i)

        if tracking_params['type'] == "freeswimming":
            if tracking_params['track_tail']:
                self.plot_tabs_widget.addTab("Tail")

            self.plot_tabs_widget.addTab("Body")

            if tracking_params['track_eyes']:
                self.plot_tabs_widget.addTab("Eyes")
        else:
            self.plot_tabs_widget.addTab("Tail")

        self.plot_tabs_widget.blockSignals(False)

        self.crop_tabs_widget.blockSignals(True)
        for i in range(self.crop_tabs_widget.count()-1, -1, -1):
            self.crop_tabs_widget.removeTab(i)

        # add crop tabs
        n_crops = len(tracking_params['crop_params'])

        for i in range(n_crops):
            self.crop_tabs_widget.addTab("{}".format(i+1))
        self.crop_tabs_widget.blockSignals(False)

    def add_tracking_item(self, item_name):
        print("Adding tracking item")
        self.tracking_list_items.append(QListWidgetItem(item_name, self.tracking_list))

        # self.update_plot()

    def change_selected_tracking_row(self, row_number):
        self.tracking_list.blockSignals(True)
        self.tracking_list.setCurrentRow(row_number)
        self.tracking_list.blockSignals(False)

    def create_tail_tracking_widget(self, parent_widget):
        # create tail tab widget & layout
        tail_tab_widget = QWidget()
        tail_tab_layout = QVBoxLayout(tail_tab_widget)

        # create button layout for tail tab
        bottom_tail_button_layout = QVBoxLayout()
        # bottom_tail_button_layout.setSpacing(5)
        bottom_tail_button_layout.addStretch(1)
        tail_tab_layout.addLayout(bottom_tail_button_layout)

        # add buttons
        track_bouts_button = QPushButton('Track Bouts', self)
        track_bouts_button.setMinimumHeight(30)
        track_bouts_button.setMaximumWidth(100)
        track_bouts_button.clicked.connect(lambda:self.controller.track_bouts())
        bottom_tail_button_layout.addWidget(track_bouts_button)

        track_freqs_button = QPushButton('Track Freq', self)
        track_freqs_button.setMinimumHeight(30)
        track_freqs_button.setMaximumWidth(100)
        track_freqs_button.clicked.connect(lambda:self.controller.track_freqs())
        bottom_tail_button_layout.addWidget(track_freqs_button)

        # add checkbox for switching plots
        self.smoothed_deriv_checkbox = QCheckBox("Show smoothed derivative")
        self.smoothed_deriv_checkbox.toggled.connect(lambda:self.show_smoothed_deriv(self.smoothed_deriv_checkbox))
        bottom_tail_button_layout.addWidget(self.smoothed_deriv_checkbox)

        # add param labels & textboxes
        smoothing_window_label = QLabel()
        smoothing_window_label.setText("Smoothing window:")
        bottom_tail_button_layout.addWidget(smoothing_window_label)

        self.smoothing_window_param_box = QLineEdit(self)
        self.smoothing_window_param_box.setMinimumHeight(20)
        self.smoothing_window_param_box.setMaximumWidth(40)
        self.smoothing_window_param_box.setText(str(self.controller.smoothing_window_width))
        bottom_tail_button_layout.addWidget(self.smoothing_window_param_box)

        threshold_label = QLabel()
        threshold_label.setText("Threshold:")
        bottom_tail_button_layout.addWidget(threshold_label)

        self.threshold_param_box = QLineEdit(self)
        self.threshold_param_box.setMinimumHeight(20)
        self.threshold_param_box.setMaximumWidth(40)
        self.threshold_param_box.setText(str(self.controller.threshold))
        bottom_tail_button_layout.addWidget(self.threshold_param_box)

        min_width_label = QLabel()
        min_width_label.setText("Min width:")
        bottom_tail_button_layout.addWidget(min_width_label)

        self.min_width_param_box = QLineEdit(self)
        self.min_width_param_box.setMinimumHeight(20)
        self.min_width_param_box.setMaximumWidth(40)
        self.min_width_param_box.setText(str(self.controller.min_width))
        bottom_tail_button_layout.addWidget(self.min_width_param_box)

        parent_widget.addWidget(tail_tab_widget)

    def create_body_tracking_widget(self, parent_widget):
        # create head tab widget & layout
        head_tab_widget = QWidget()
        head_tab_layout = QVBoxLayout(head_tab_widget)

        # create button layout for head tab
        bottom_head_button_layout = QHBoxLayout()
        head_tab_layout.addLayout(bottom_head_button_layout)

        # add buttons
        track_position_button = QPushButton('Track Pos', self)
        track_position_button.setMinimumHeight(30)
        track_position_button.setMaximumWidth(100)
        track_position_button.clicked.connect(lambda:self.track_position())
        bottom_head_button_layout.addWidget(track_position_button)

        # add checkbox for switching plots
        speed_checkbox = QCheckBox("Show speed")
        speed_checkbox.toggled.connect(lambda:self.show_speed(self.speed_checkbox))
        bottom_head_button_layout.addWidget(speed_checkbox)

        parent_widget.addWidget(head_tab_widget)

    def create_crops(self, parent_layout):
        crop_tabs_widget = QTabWidget()
        crop_tabs_widget.currentChanged.connect(self.change_crop)
        crop_tabs_widget.setElideMode(Qt.ElideLeft)
        crop_tabs_layout = QVBoxLayout(crop_tabs_widget)
        parent_layout.addWidget(crop_tabs_widget)

        self.crop_tabs_widgets.append(crop_tabs_widget)
        self.crop_tabs_layouts.append(crop_tabs_layout)

        n_crops = len(self.controller.tracking_params[self.controller.curr_tracking_num]['crop_params'])

        for k in range(n_crops):
            self.create_crop()

    def clear_crops(self):
        self.crop_tab_layouts  = [[]]
        self.crop_tab_widgets  = [[]]
        self.plot_tab_layouts  = [{'tail': [],
                                  'eyes': [],
                                  'body': []}]
        self.plot_tab_widgets  = [{'tail': [],
                                  'eyes': [],
                                  'body': []}]
        self.plot_tabs_widgets = [[]]
        self.plot_tabs_layouts = [[]]

        self.head_angle_arrays = []
        self.tail_angle_arrays = []

        for c in range(self.n_crops-1, -1, -1):
            # remove tab
            self.crop_tabs_widget.removeTab(c)

        self.n_crops = 0
        self.current_crop = -1

    def show_smoothed_deriv(self, checkbox):
        if self.smoothed_abs_deriv_abs_angle_array != None:
            if checkbox.isChecked():
                self.tail_canvas.plot_tail_angle_array(self.smoothed_abs_deriv_abs_angle_array, self.bouts, keep_limits=True)
            else:
                self.tail_canvas.plot_tail_angle_array(self.tail_end_angle_array[self.current_crop], self.bouts, self.peak_maxes_y, self.peak_maxes_x, self.peak_mins_y, self.peak_mins_x, self.freqs, keep_limits=True)

    def show_speed(self, checkbox):
        if self.speed_array != None:
            if checkbox.isChecked():
                self.head_canvas.plot_head_array(self.speed_array, keep_limits=True)
            else:
                self.head_canvas.plot_head_array(self.head_angle_array, keep_limits=True)

    def load_data(self, data_path=None):
        if data_path == None:
            # ask the user to select a directory
            self.path = str(QFileDialog.getExistingDirectory(self, 'Open folder'))
        else:
            self.path = data_path

        # load saved tracking data
        (self.tail_coords_array, self.spline_coords_array,
         self.heading_angle_array, self.body_position_array,
         self.eye_coords_array, self.params) = an.open_saved_data(self.path)

        if self.params != None:
            # calculate tail angles
            if self.params['type'] == "freeswimming" and self.params['track_tail']:
                self.tail_angle_array = an.get_freeswimming_tail_angles(self.tail_coords_array, self.heading_angle_array, self.body_position_array)
            elif self.params['type'] == "headfixed":
                self.tail_angle_array = an.get_headfixed_tail_angles(self.tail_coords_array, self.params['tail_direction'])

            # get array of average angle of the last few points of the tail
            # self.tail_end_angle_array = np.mean(self.tail_angle_array[:, :, -3:], axis=-1)
            # self.tail_end_angle_array = self.tail_angle_array[:, :, -1]
            self.tail_end_angle_array = an.get_tail_end_angles(self.tail_angle_array, num_to_average=3)
            
            # clear crops
            self.clear_crops()

            # get number of saved crops
            n_crops_total = len(self.params['crop_params'])

            for k in range(n_crops_total):
                # create a crop
                self.create_crop()

                # plot heading angle
                if self.heading_angle_array is not None:
                    self.plot_canvases[k].plot_heading_angle_array(self.heading_angle_array[k])

                # plot tail angle
                if self.tail_angle_array is not None:
                    self.tail_canvases[k].plot_tail_angle_array(self.tail_end_angle_array[k])

    # def track_bouts(self):
    #     if self.tail_angle_array != None:
    #         # get params
    #         self.smoothing_window_width = int(self.smoothing_window_param_box.text())
    #         self.threshold = float(self.threshold_param_box.text())
    #         self.min_width = int(self.min_width_param_box.text())

    #         # get smoothed derivative
    #         abs_angle_array = np.abs(self.tail_end_angle_array[self.current_crop])
    #         deriv_abs_angle_array = np.gradient(abs_angle_array)
    #         abs_deriv_abs_angle_array = np.abs(deriv_abs_angle_array)
    #         normpdf = scipy.stats.norm.pdf(range(-int(self.smoothing_window_width/2),int(self.smoothing_window_width/2)),0,3)
    #         self.smoothed_abs_deriv_abs_angle_array =  np.convolve(abs_deriv_abs_angle_array,  normpdf/np.sum(normpdf),mode='valid')

    #         # calculate bout periods
    #         self.bouts = an.contiguous_regions(self.smoothed_abs_deriv_abs_angle_array > self.threshold)

    #         # remove bouts that don't have the minimum bout length
    #         for i in range(self.bouts.shape[0]-1, -1, -1):
    #             if self.bouts[i, 1] - self.bouts[i, 0] < self.min_width:
    #                 self.bouts = np.delete(self.bouts, (i), 0)

    #         # update plot
    #         self.smoothed_deriv_checkbox.setChecked(False)
    #         self.tail_canvas.plot_tail_angle_array(self.tail_end_angle_array[self.current_crop], self.bouts, keep_limits=True)

    # def track_freqs(self):
    #     if self.bouts != None:
    #         # initiate bout maxima & minima coord lists
    #         self.peak_maxes_y = []
    #         self.peak_maxes_x = []
    #         self.peak_mins_y = []
    #         self.peak_mins_x = []

    #         # initiate instantaneous frequency array
    #         self.freqs = np.zeros(self.tail_angle_array.shape[0])

    #         for i in range(self.bouts.shape[0]):
    #             # get local maxima & minima
    #             peak_max, peak_min = peakdetect.peakdet(self.tail_end_angle_array[self.current_crop][self.bouts[i, 0]:self.bouts[i, 1]], 0.02)

    #             # change local coordinates (relative to the start of the bout) to global coordinates
    #             peak_max[:, 0] += self.bouts[i, 0]
    #             peak_min[:, 0] += self.bouts[i, 0]

    #             # add to the bout maxima & minima coord lists
    #             self.peak_maxes_y += list(peak_max[:, 1])
    #             self.peak_maxes_x += list(peak_max[:, 0])
    #             self.peak_mins_y += list(peak_min[:, 1])
    #             self.peak_mins_x += list(peak_min[:, 0])

    #         # calculate instantaneous frequencies
    #         for i in range(len(self.peak_maxes_x)-1):
    #             self.freqs[self.peak_maxes_x[i]:self.peak_maxes_x[i+1]] = 1.0/(self.peak_maxes_x[i+1] - self.peak_maxes_x[i])

    #         # update plot
    #         self.smoothed_deriv_checkbox.setChecked(False)
    #         self.tail_canvas.plot_tail_angle_array(self.tail_end_angle_array[self.current_crop], self.bouts, self.peak_maxes_y, self.peak_maxes_x, self.peak_mins_y, self.peak_mins_x, self.freqs, keep_limits=True)

    def track_position(self):
        if self.head_angle_array != None:
            # get params
            self.smoothing_window_width = int(self.smoothing_window_param_box.text())

            abs_angle_array = np.abs(self.tail_angle_array)
            deriv_abs_angle_array = np.gradient(abs_angle_array)
            abs_deriv_abs_angle_array = np.abs(deriv_abs_angle_array)
            self.smoothed_abs_deriv_abs_angle_array = np.convolve(abs_deriv_abs_angle_array, np.ones((self.smoothing_window_width,))/self.smoothing_window_width, mode='valid')

            positions_y, positions_x, self.speed_array = an.get_position_history(self.path, plot=False)

    def fileQuit(self):
        self.close()

    def closeEvent(self, event):
        self.controller.close_all()

    def resizeEvent(self, re):
        QMainWindow.resizeEvent(self, re)
Example #37
0
class ImportWindow(QWidget):
    def __init__(self, parent, doc):
        QWidget.__init__(self, parent, Qt.Window)
        self._setupUi()
        self.doc = doc
        self.model = ImportWindowModel(document=doc.model)
        self.swapOptionsComboBox = ComboboxModel(model=self.model.swap_type_list, view=self.swapOptionsComboBoxView)
        self.table = ImportTable(model=self.model.import_table, view=self.tableView)
        self.model.view = self
        self._setupColumns() # Can only be done after the model has been connected
        
        self.tabView.tabCloseRequested.connect(self.tabCloseRequested)
        self.tabView.currentChanged.connect(self.currentTabChanged)
        self.targetAccountComboBox.currentIndexChanged.connect(self.targetAccountChanged)
        self.importButton.clicked.connect(self.importClicked)
        self.swapButton.clicked.connect(self.swapClicked)
    
    def _setupUi(self):
        self.setWindowTitle(tr("Import"))
        self.resize(557, 407)
        self.verticalLayout = QtGui.QVBoxLayout(self)
        self.tabView = QTabBar(self)
        self.tabView.setMinimumSize(QtCore.QSize(0, 20))
        self.verticalLayout.addWidget(self.tabView)
        self.targetAccountLayout = QtGui.QHBoxLayout()
        self.targetAccountLabel = QtGui.QLabel(tr("Target Account:"))
        self.targetAccountLayout.addWidget(self.targetAccountLabel)
        self.targetAccountComboBox = QComboBox(self)
        self.targetAccountComboBox.setMinimumSize(QtCore.QSize(150, 0))
        self.targetAccountLayout.addWidget(self.targetAccountComboBox)
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.targetAccountLayout.addItem(spacerItem)
        self.groupBox = QGroupBox(tr("Are some fields wrong? Fix them!"))
        self.gridLayout = QtGui.QGridLayout(self.groupBox)
        self.swapOptionsComboBoxView = QComboBox(self.groupBox)
        self.gridLayout.addWidget(self.swapOptionsComboBoxView, 0, 0, 1, 2)
        self.applyToAllCheckBox = QtGui.QCheckBox(tr("Apply to all accounts"))
        self.gridLayout.addWidget(self.applyToAllCheckBox, 1, 0, 1, 1)
        self.swapButton = QPushButton(tr("Fix"))
        self.gridLayout.addWidget(self.swapButton, 1, 1, 1, 1)
        self.targetAccountLayout.addWidget(self.groupBox)
        self.verticalLayout.addLayout(self.targetAccountLayout)
        self.tableView = TableView(self)
        self.tableView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.tableView.setDragEnabled(True)
        self.tableView.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.tableView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableView.horizontalHeader().setHighlightSections(False)
        self.tableView.horizontalHeader().setMinimumSectionSize(18)
        self.tableView.verticalHeader().setVisible(False)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.verticalLayout.addWidget(self.tableView)
        self.horizontalLayout = QtGui.QHBoxLayout()
        spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)
        self.importButton = QPushButton(tr("Import"))
        self.horizontalLayout.addWidget(self.importButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.tabView.setTabsClosable(True)
        self.tabView.setDrawBase(False)
        self.tabView.setDocumentMode(True)
        self.tabView.setUsesScrollButtons(True)
    
    def _setupColumns(self):
        # Can't set widget alignment in a layout in the Designer
        l = self.targetAccountLayout
        l.setAlignment(self.targetAccountLabel, Qt.AlignTop)
        l.setAlignment(self.targetAccountComboBox, Qt.AlignTop)
    
    #--- Event Handlers
    def currentTabChanged(self, index):
        self.model.selected_pane_index = index
    
    def importClicked(self):
        self.model.import_selected_pane()
    
    def swapClicked(self):
        applyToAll = self.applyToAllCheckBox.isChecked()
        self.model.perform_swap(applyToAll)
    
    def tabCloseRequested(self, index):
        self.model.close_pane(index)
        self.tabView.removeTab(index)
    
    def targetAccountChanged(self, index):
        self.model.selected_target_account_index = index
        self.table.updateColumnsVisibility()
    
    #--- model --> view
    def close(self):
        self.hide()
    
    def close_selected_tab(self):
        self.tabView.removeTab(self.tabView.currentIndex())
    
    def refresh_target_accounts(self):
        # We disconnect the combobox because we don't want the clear() call to set the selected 
        # target index in the model.
        self.targetAccountComboBox.currentIndexChanged.disconnect(self.targetAccountChanged)
        self.targetAccountComboBox.clear()
        self.targetAccountComboBox.addItems(self.model.target_account_names)
        self.targetAccountComboBox.currentIndexChanged.connect(self.targetAccountChanged)
    
    def refresh_tabs(self):
        while self.tabView.count():
            self.tabView.removeTab(0)
        for pane in self.model.panes:
            self.tabView.addTab(pane.name)
    
    def set_swap_button_enabled(self, enabled):
        self.swapButton.setEnabled(enabled)
    
    def show(self):
        # For non-modal dialogs, show() is not enough to bring the window at the forefront, we have
        # to call raise() as well
        QWidget.show(self)
        self.raise_()
    
    def update_selected_pane(self):
        index = self.model.selected_pane_index
        if index != self.tabView.currentIndex(): # this prevents infinite loops
            self.tabView.setCurrentIndex(index)
        self.targetAccountComboBox.setCurrentIndex(self.model.selected_target_account_index)
        self.table.updateColumnsVisibility()
 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)
Example #39
0
 def __init__(self,parent):
     QTabBar.__init__(self,parent)
     self.setAcceptDrops(True)
     self.setMouseTracking(True)
	def __init__(self, parent=None):
		QTabBar.__init__(self,parent)