Esempio n. 1
0
File: Kuad.py Progetto: szilm/Kuad
class KuadApplication (KApplication):
    def __init__(self):
        super(KApplication, self).__init__()
        
        self.mainwin = kparts.KParts.MainWindow(None, Qt.FramelessWindowHint) # No titlebar
        
        self.loader = KPluginLoader('libkonsolepart')
        self.factory = self.loader.factory()		

        width = 2
        height = 2
        self.splitter = QSplitter(Qt.Vertical)
        for v in range(width):
            splitter = QSplitter(Qt.Horizontal)
            
            for h in range(height):
                widget = KonsoleWidget(splitter, self)
                splitter.insertWidget(h, widget)
            self.splitter.insertWidget(v,splitter)
        
        self.mainwin.setCentralWidget(self.splitter)
        #QShortcut(QKeySequence('Ctrl+Q'), self.mainwin, self.quit)
        
        self.mainwin.showMaximized()
        
    def eventFilter(self, object, event):
        if event.type() == QEvent.KeyPress:
            print 'eat keypress'
            return True
        return False
Esempio n. 2
0
class Help(QDockWidget):
    def __init__(self, parent=None, path=None):
        QDockWidget.__init__(self, parent)
        self.name = self.tr("Help")
        self.setFloating(False)
        self.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.__mainWidget = QSplitter(Qt.Horizontal)
        self.__uname = QWidget()

        mainWidgetLayout = QVBoxLayout(self.__uname)
        mainWidgetLayout.setContentsMargins(0, 0, 0, 0)

        # create helper + search engine
        self.__helper = QHelpEngine(path, self)

        if not self.__helper.setupData() is True:
            dialog = QMessageBox()
            
            msg = QString(self.tr("An error occurred while setting help engine up :\n"))
            msg += (self.__helper.error() + "\n")
            msg += self.tr("It might mean that the format of your help file is not correct.\n")
            msg += self.tr("You can check on-line help at http://wiki.digital-forensic.org")

            dialog.setText(msg)
            dialog.setIcon(QMessageBox.Warning)
            dialog.setWindowTitle(self.tr("Error while loading help"))
            dialog.exec_()
            return

        self.__toc = self.__helper.contentWidget()
        self.__helpBrowser = HelpBrowser(self.__helper)

        # build main widget
        self.__toolbar = QWidget()
        self.__toolbarLayout = QHBoxLayout(self.__toolbar)
        home = QPushButton(QIcon(":home.png"), "")
        previous = QPushButton(QIcon(":previous.png"), "")
        next = QPushButton(QIcon(":next.png"), "")

        # building toolbar
        self.__toolbarLayout.addWidget(home)
        self.__toolbarLayout.addWidget(previous)
        self.__toolbarLayout.addWidget(next)
        self.__toolbarLayout.setContentsMargins(0, 0, 0, 0)
        mainWidgetLayout.addWidget(self.__toolbar)
        mainWidgetLayout.addWidget(self.__helpBrowser)
        self.__mainWidget.insertWidget(0, self.__toc)
        self.__mainWidget.insertWidget(1, self.__uname)
        self.__mainWidget.setStretchFactor(1, 1)
        self.setWidget(self.__mainWidget)

        #connecting `previous`, `home` and `next` buttons
        self.connect(next, SIGNAL("clicked(bool)"), self.__helpBrowser.nextPage)
        self.connect(previous, SIGNAL("clicked(bool)"), self.__helpBrowser.prevPage)
        self.connect(home, SIGNAL("clicked(bool)"), self.__helpBrowser.goHome)
        self.connect(self.__helper.contentWidget(), SIGNAL("linkActivated(const QUrl &)"),
                     self.__helpBrowser.setSource)
Esempio n. 3
0
File: Kuad.py Progetto: szilm/Kuad
    def __init__(self):
        super(KApplication, self).__init__()
        
        self.mainwin = kparts.KParts.MainWindow(None, Qt.FramelessWindowHint) # No titlebar
        
        self.loader = KPluginLoader('libkonsolepart')
        self.factory = self.loader.factory()		

        width = 2
        height = 2
        self.splitter = QSplitter(Qt.Vertical)
        for v in range(width):
            splitter = QSplitter(Qt.Horizontal)
            
            for h in range(height):
                widget = KonsoleWidget(splitter, self)
                splitter.insertWidget(h, widget)
            self.splitter.insertWidget(v,splitter)
        
        self.mainwin.setCentralWidget(self.splitter)
        #QShortcut(QKeySequence('Ctrl+Q'), self.mainwin, self.quit)
        
        self.mainwin.showMaximized()
Esempio n. 4
0
class __CentralWidget(QWidget):

    ###############################################################################
    # CentralWidget SIGNALS
    ###############################################################################
    """
    splitterCentralRotated()
    """

    ###############################################################################

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.parent = parent
        #This variables are used to save the splitter sizes before hide
        self._splitterMainSizes = None
        self._splitterAreaSizes = None
        self.lateralPanel = None

        hbox = QHBoxLayout(self)
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.setSpacing(0)
        #Create Splitters to divide the UI in: MainPanel, Explorer, Misc
        self._splitterArea = QSplitter(Qt.Horizontal)
        self._splitterMain = QSplitter(Qt.Vertical)

        #Create scrollbar for follow mode
        self.scrollBar = QScrollBar(Qt.Vertical, self)
        self.scrollBar.setFixedWidth(20)
        self.scrollBar.setToolTip('Follow Mode: Scroll the Editors together')
        self.scrollBar.hide()
        self.connect(self.scrollBar, SIGNAL("valueChanged(int)"),
                     self.move_follow_scrolls)

        #Add to Main Layout
        hbox.addWidget(self.scrollBar)
        hbox.addWidget(self._splitterArea)

    def insert_central_container(self, container):
        self.mainContainer = container
        self._splitterMain.insertWidget(0, container)

    def insert_lateral_container(self, container):
        self.lateralPanel = LateralPanel(container)
        self._splitterArea.insertWidget(0, self.lateralPanel)

    def insert_bottom_container(self, container):
        self.misc = container
        self._splitterMain.insertWidget(1, container)

    def showEvent(self, event):
        #Show Event
        QWidget.showEvent(self, event)
        #Avoid recalculate the panel sizes if they are already loaded
        if self._splitterArea.count() == 2:
            return
        #Rearrange widgets on Window
        self._splitterArea.insertWidget(0, self._splitterMain)
        qsettings = QSettings()
        #Lists of sizes as list of QVariant- heightList = [QVariant, QVariant]
        heightList = list(
            qsettings.value("window/central/mainSize",
                            [(self.height() / 3) * 2,
                             self.height() / 3]))
        widthList = list(
            qsettings.value("window/central/areaSize", [(self.width() / 6) * 5,
                                                        self.width() / 6]))
        self._splitterMainSizes = [int(heightList[0]), int(heightList[1])]
        self._splitterAreaSizes = [int(widthList[0]), int(widthList[1])]
        if not event.spontaneous():
            self.change_misc_visibility()
        if bin(settings.UI_LAYOUT)[-1] == '1':
            self.splitter_central_rotate()
        if bin(settings.UI_LAYOUT >> 1)[-1] == '1':
            self.splitter_misc_rotate()
        if bin(settings.UI_LAYOUT >> 2)[-1] == '1':
            self.splitter_central_orientation()
        #Set the sizes to splitters
        self._splitterMain.setSizes(self._splitterMainSizes)
        self._splitterArea.setSizes(self._splitterAreaSizes)
        self.misc.setVisible(
            qsettings.value("window/show_misc", False, type=bool))

    def change_misc_visibility(self):
        if self.misc.isVisible():
            self._splitterMainSizes = self._splitterMain.sizes()
            self.misc.hide()
            widget = self.mainContainer.get_actual_widget()
            if widget:
                widget.setFocus()
        else:
            self.misc.show()
            self.misc.gain_focus()

    def change_main_visibility(self):
        if self.mainContainer.isVisible():
            self.mainContainer.hide()
        else:
            self.mainContainer.show()

    def change_explorer_visibility(self, force_hide=False):
        if self.lateralPanel.isVisible() or force_hide:
            self._splitterAreaSizes = self._splitterArea.sizes()
            self.lateralPanel.hide()
        else:
            self.lateralPanel.show()

    def splitter_central_rotate(self):
        w1, w2 = self._splitterArea.widget(0), self._splitterArea.widget(1)
        self._splitterArea.insertWidget(0, w2)
        self._splitterArea.insertWidget(1, w1)
        self.emit(SIGNAL("splitterCentralRotated()"))

    def splitter_central_orientation(self):
        if self._splitterArea.orientation() == Qt.Horizontal:
            self._splitterArea.setOrientation(Qt.Vertical)
        else:
            self._splitterArea.setOrientation(Qt.Horizontal)

    def splitter_misc_rotate(self):
        w1, w2 = self._splitterMain.widget(0), self._splitterMain.widget(1)
        self._splitterMain.insertWidget(0, w2)
        self._splitterMain.insertWidget(1, w1)

    def splitter_misc_orientation(self):
        if self._splitterMain.orientation() == Qt.Horizontal:
            self._splitterMain.setOrientation(Qt.Vertical)
        else:
            self._splitterMain.setOrientation(Qt.Horizontal)

    def get_area_sizes(self):
        if self.lateralPanel.isVisible():
            self._splitterAreaSizes = self._splitterArea.sizes()
        return self._splitterAreaSizes

    def get_main_sizes(self):
        if self.misc.isVisible():
            self._splitterMainSizes = self._splitterMain.sizes()
        return self._splitterMainSizes

    def enable_follow_mode_scrollbar(self, val):
        if val:
            editorWidget = self.mainContainer.get_actual_editor()
            maxScroll = editorWidget.verticalScrollBar().maximum()
            position = editorWidget.verticalScrollBar().value()
            self.scrollBar.setMaximum(maxScroll)
            self.scrollBar.setValue(position)
        self.scrollBar.setVisible(val)

    def move_follow_scrolls(self, val):
        widget = self.mainContainer._tabMain.currentWidget()
        diff = widget._sidebarWidget.highest_line - val
        s1 = self.mainContainer._tabMain.currentWidget().verticalScrollBar()
        s2 = self.mainContainer._tabSecondary.\
            currentWidget().verticalScrollBar()
        s1.setValue(val)
        s2.setValue(val + diff)
Esempio n. 5
0
class MikiWindow(QMainWindow):
    def __init__(self, settings, parent=None):
        super(MikiWindow, self).__init__(parent)
        self.setObjectName("mikiWindow")
        self.settings = settings
        self.notePath = settings.notePath
        lockPath = os.path.join(settings.notebookPath, '.mikidown_lock')
        if not os.path.exists(lockPath):
            self.lockPathFH = os.open(lockPath,
                                      os.O_CREAT | os.O_EXCL | os.O_RDWR)
        ################ Setup core components ################
        self.notesTree = MikiTree(self)
        self.quickNoteNav = QLineEdit()
        self.notesTab = QWidget()
        self.completer = SlashPleter()
        self.completer.setModel(self.notesTree.model())
        self.quickNoteNav.setCompleter(self.completer)
        self.notesTree.setObjectName("notesTree")
        self.initTree(self.notePath, self.notesTree)
        self.notesTree.sortItems(0, Qt.AscendingOrder)

        self.ix = None
        self.setupWhoosh()

        self.viewedList = QToolBar(self.tr('Recently Viewed'), self)
        self.viewedList.setIconSize(QSize(16, 16))
        self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.viewedListActions = []
        self.noteSplitter = QSplitter(Qt.Horizontal)

        self.dockIndex = QDockWidget(self.tr("Index"))
        self.dockSearch = QDockWidget(self.tr("Search"))
        self.searchEdit = QLineEdit()
        self.searchView = MikiSearch(self)
        self.searchTab = QWidget()
        self.dockToc = QDockWidget(self.tr("TOC"))
        self.tocTree = TocTree()
        self.dockAttachment = QDockWidget(self.tr("Attachment"))
        self.attachmentView = AttachmentView(self)

        self.notesEdit = MikiEdit(self)
        self.notesEdit.setObjectName(self.tr("notesEdit"))
        self.loadHighlighter()
        self.notesView = MikiView(self)

        self.findBar = QToolBar(self.tr('Find'), self)
        self.findBar.setFixedHeight(30)
        self.findEdit = QLineEdit(self.findBar)
        self.checkBox = QCheckBox(self.tr('Match case'), self.findBar)

        self.statusBar = QStatusBar(self)
        self.statusLabel = QLabel(self)

        self.altPressed = False

        ################ Setup actions ################
        self.actions = dict()
        self.setupActions()

        ################ Setup mainwindow ################
        self.setupMainWindow()

        # show changelogs after upgrade mikidown
        if self.settings.version < __version__ or Mikibook.settings.value(
                "version", defaultValue="0") < __version__:
            self.changelogHelp()
            self.settings.qsettings.setValue("version", __version__)
            Mikibook.settings.setValue("version", __version__)

    def loadHighlighter(self):
        fnt = Mikibook.settings.value('editorFont', defaultValue=None)
        fntsize = Mikibook.settings.value('editorFontSize',
                                          type=int,
                                          defaultValue=12)
        header_scales_font = Mikibook.settings.value('headerScaleFont',
                                                     type=bool,
                                                     defaultValue=True)
        if fnt is not None:
            self.notesEdit.setFontFamily(fnt)
            self.notesEdit.setFontPointSize(fntsize)
        h = MikiHighlighter(parent=self.notesEdit,
                            scale_font_sizes=header_scales_font)
        tw = Mikibook.settings.value('tabWidth', type=int, defaultValue=4)
        qfm = QFontMetrics(h.patterns[0][1].font())
        self.notesEdit.setTabStopWidth(tw * qfm.width(' '))

    def setupActions(self):

        # Global Actions
        actTabIndex = self.act(self.tr('Switch to Index Tab'),
                               lambda: self.raiseDock(self.dockIndex),
                               self.tr('Ctrl+Shift+I'))
        actTabSearch = self.act(self.tr('Switch to Search Tab'),
                                lambda: self.raiseDock(self.dockSearch),
                                self.tr('Ctrl+Shift+F'))
        self.addAction(actTabIndex)
        self.addAction(actTabSearch)

        ################ Menu Actions ################
        # actions in menuFile
        actionNewPage = self.act(self.tr('&New Page...'),
                                 self.notesTree.newPage, QKeySequence.New)
        self.actions.update(newPage=actionNewPage)

        actionNewSubpage = self.act(self.tr('New Sub&page...'),
                                    self.notesTree.newSubpage,
                                    self.tr('Ctrl+Shift+N'))
        self.actions.update(newSubpage=actionNewSubpage)

        actionImportPage = self.act(self.tr('&Import Page...'),
                                    self.importPage)
        self.actions.update(importPage=actionImportPage)

        actionNBSettings = self.act(self.tr('Notebook Set&tings...'),
                                    self.notebookSettings)
        self.actions.update(NBSettings=actionNBSettings)

        actionMDSettings = self.act(self.tr('&Mikidown Settings...'),
                                    self.mikidownSettings)
        self.actions.update(MDSettings=actionMDSettings)

        actionOpenNotebook = self.act(self.tr('&Open Notebook...'),
                                      self.openNotebook, QKeySequence.Open)
        self.actions.update(openNotebook=actionOpenNotebook)

        actionReIndex = self.act(self.tr('Re-index'), self.reIndex)
        self.actions.update(reIndex=actionReIndex)

        actionSave = self.act(self.tr('&Save'), self.saveCurrentNote,
                              QKeySequence.Save)
        actionSave.setEnabled(False)
        self.actions.update(save=actionSave)

        actionSaveAs = self.act(self.tr('Save &As...'), self.saveNoteAs,
                                QKeySequence.SaveAs)
        self.actions.update(saveAs=actionSaveAs)

        actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml)
        self.actions.update(html=actionHtml)

        actionPrint = self.act(self.tr('&Print'), self.printNote,
                               QKeySequence.Print)
        self.actions.update(print_=actionPrint)

        actionRenamePage = self.act(self.tr('&Rename Page...'),
                                    self.notesTree.renamePage, 'F2')
        self.actions.update(renamePage=actionRenamePage)

        actionDelPage = self.act(self.tr('&Delete Page'),
                                 self.notesTree.delPageWrapper,
                                 QKeySequence.Delete)
        self.actions.update(delPage=actionDelPage)

        actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit)
        actionQuit.setMenuRole(QAction.QuitRole)
        self.actions.update(quit=actionQuit)

        # actions in menuEdit
        actionUndo = self.act(self.tr('&Undo'), lambda: self.notesEdit.undo(),
                              QKeySequence.Undo)
        actionUndo.setEnabled(False)
        self.notesEdit.undoAvailable.connect(actionUndo.setEnabled)
        self.actions.update(undo=actionUndo)

        actionRedo = self.act(self.tr('&Redo'), lambda: self.notesEdit.redo(),
                              QKeySequence.Redo)
        actionRedo.setEnabled(False)
        self.notesEdit.redoAvailable.connect(actionRedo.setEnabled)
        self.actions.update(redo=actionRedo)

        actionFindText = self.act(self.tr('&Find Text'),
                                  self.findBar.setVisible, QKeySequence.Find,
                                  True)
        self.actions.update(findText=actionFindText)

        actionFindRepl = self.act(self.tr('Find and Replace'),
                                  FindReplaceDialog(self.notesEdit).open,
                                  QKeySequence.Replace)
        self.actions.update(findRepl=actionFindRepl)

        actionFind = self.act(self.tr('Next'), self.findText,
                              QKeySequence.FindNext)
        self.actions.update(find=actionFind)

        actionFindPrev = self.act(self.tr('Previous'),
                                  lambda: self.findText(back=True),
                                  QKeySequence.FindPrevious)
        self.actions.update(findPrev=actionFindPrev)

        actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines)
        self.actions.update(sortLines=actionSortLines)

        actionQuickNav = self.act(self.tr("&Quick Open Note"),
                                  self.quickNoteNav.setFocus,
                                  self.tr('Ctrl+G'))
        self.addAction(actionQuickNav)

        actionInsertImage = self.act(self.tr('&Insert Attachment'),
                                     self.notesEdit.insertAttachmentWrapper,
                                     self.tr('Ctrl+I'))
        actionInsertImage.setEnabled(False)
        self.actions.update(insertImage=actionInsertImage)

        # actions in menuView
        QIcon.setThemeName(
            Mikibook.settings.value('iconTheme', QIcon.themeName()))
        #print(QIcon.themeName())
        actionEdit = self.act(self.tr('Edit'), self.edit, self.tr('Ctrl+E'),
                              True, QIcon.fromTheme('document-edit'),
                              self.tr('Edit mode (Ctrl+E)'))
        self.actions.update(edit=actionEdit)

        actionSplit = self.act(self.tr('Split'), self.liveView,
                               self.tr('Ctrl+R'), True,
                               QIcon.fromTheme('view-split-left-right'),
                               self.tr('Split mode (Ctrl+R)'))
        self.actions.update(split=actionSplit)

        actionFlipEditAndView = self.act(self.tr('Flip Edit and View'),
                                         self.flipEditAndView)
        actionFlipEditAndView.setEnabled(False)
        self.actions.update(flipEditAndView=actionFlipEditAndView)

        #actionLeftAndRight = self.act(
        #    self.tr('Split into Left and Right'), trig=self.leftAndRight)
        #actionUpAndDown = self.act(
        #    self.tr('Split into Up and Down'), trig=self.upAndDown)
        # self.actionLeftAndRight.setEnabled(False)
        # self.actionUpAndDown.setEnabled(False)

        # actions in menuHelp
        actionReadme = self.act(self.tr('README'), self.readmeHelp)
        self.actions.update(readme=actionReadme)

        actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp)
        self.actions.update(changelog=actionChangelog)

        actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt)
        self.actions.update(aboutQt=actionAboutQt)

    def setupMainWindow(self):
        self.resize(800, 600)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
        self.setWindowTitle('{} - {}'.format(self.settings.notebookName,
                                             __appname__))

        self.viewedList.setFixedHeight(25)
        self.noteSplitter.addWidget(self.notesEdit)
        self.noteSplitter.addWidget(self.notesView)
        mainSplitter = QSplitter(Qt.Vertical)
        mainSplitter.setChildrenCollapsible(False)
        mainSplitter.addWidget(self.viewedList)
        mainSplitter.addWidget(self.noteSplitter)
        mainSplitter.addWidget(self.findBar)
        self.setCentralWidget(mainSplitter)

        self.searchEdit.returnPressed.connect(self.searchNote)
        self.quickNoteNav.returnPressed.connect(self.openFuncWrapper)
        searchLayout = QVBoxLayout()
        searchLayout.addWidget(self.searchEdit)
        searchLayout.addWidget(self.searchView)
        self.searchTab.setLayout(searchLayout)

        indexLayout = QVBoxLayout(self.notesTab)
        indexLayout.addWidget(self.quickNoteNav)
        indexLayout.addWidget(self.notesTree)

        self.dockIndex.setObjectName("Index")
        self.dockIndex.setWidget(self.notesTab)
        self.dockSearch.setObjectName("Search")
        self.dockSearch.setWidget(self.searchTab)
        self.dockToc.setObjectName("TOC")
        self.dockToc.setWidget(self.tocTree)
        self.dockAttachment.setObjectName("Attachment")
        self.dockAttachment.setWidget(self.attachmentView)

        self.setDockOptions(QMainWindow.VerticalTabs)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment)
        self.tabifyDockWidget(self.dockIndex, self.dockSearch)
        self.tabifyDockWidget(self.dockSearch, self.dockToc)
        self.tabifyDockWidget(self.dockToc, self.dockAttachment)
        self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North)
        self.dockIndex.raise_()  # Put dockIndex on top of the tab stack

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        menuFile = menuBar.addMenu(self.tr('&File'))
        menuEdit = menuBar.addMenu(self.tr('&Edit'))
        menuView = menuBar.addMenu(self.tr('&View'))
        menuHelp = menuBar.addMenu(self.tr('&Help'))
        # menuFile
        menuFile.addAction(self.actions['newPage'])
        menuFile.addAction(self.actions['newSubpage'])
        menuFile.addAction(self.actions['NBSettings'])
        menuFile.addAction(self.actions['MDSettings'])
        menuFile.addAction(self.actions['importPage'])
        menuFile.addAction(self.actions['openNotebook'])
        menuFile.addAction(self.actions['reIndex'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['save'])
        menuFile.addAction(self.actions['saveAs'])
        menuFile.addAction(self.actions['print_'])
        menuExport = menuFile.addMenu(self.tr('&Export'))
        menuExport.addAction(self.actions['html'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['renamePage'])
        menuFile.addAction(self.actions['delPage'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['quit'])
        # menuEdit
        menuEdit.addAction(self.actions['undo'])
        menuEdit.addAction(self.actions['redo'])
        menuEdit.addAction(self.actions['findText'])
        menuEdit.addAction(self.actions['findRepl'])
        menuEdit.addSeparator()
        menuEdit.addAction(self.actions['sortLines'])
        menuEdit.addAction(self.actions['insertImage'])
        # menuView
        menuView.addAction(self.actions['edit'])
        menuView.addAction(self.actions['split'])
        menuView.addAction(self.actions['flipEditAndView'])
        menuShowHide = menuView.addMenu(self.tr('Show/Hide'))
        menuShowHide.addAction(self.dockIndex.toggleViewAction())
        menuShowHide.addAction(self.dockSearch.toggleViewAction())
        menuShowHide.addAction(self.dockToc.toggleViewAction())
        menuShowHide.addAction(self.dockAttachment.toggleViewAction())
        #menuMode = menuView.addMenu(self.tr('Mode'))
        #menuMode.addAction(self.actionLeftAndRight)
        #menuMode.addAction(self.actionUpAndDown)
        # menuHelp
        menuHelp.addAction(self.actions['readme'])
        menuHelp.addAction(self.actions['changelog'])
        menuHelp.addAction(self.actions['aboutQt'])

        toolBar = QToolBar(self.tr("toolbar"), self)
        toolBar.setObjectName("toolbar")  # needed in saveState()
        #toolBar.setIconSize(QSize(16, 16))
        toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.addToolBar(Qt.TopToolBarArea, toolBar)
        toolBar.addAction(self.actions['edit'])
        toolBar.addAction(self.actions['split'])
        self.findEdit.returnPressed.connect(self.findText)
        self.findBar.addWidget(self.findEdit)
        self.findBar.addWidget(self.checkBox)
        self.findBar.addAction(self.actions['findPrev'])
        self.findBar.addAction(self.actions['find'])
        self.findBar.setVisible(False)
        self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged)

        self.setStatusBar(self.statusBar)
        self.statusBar.addWidget(self.statusLabel, 1)

        self.notesTree.currentItemChanged.connect(
            self.currentItemChangedWrapper)
        self.notesTree.nvwCallback = self.newNoteDisplay
        self.notesTree.nvwtCallback = self.newPlainTextNoteDisplay
        self.tocTree.itemClicked.connect(self.tocNavigate)
        self.notesEdit.textChanged.connect(self.noteEditted)

        self.notesEdit.document().modificationChanged.connect(
            self.modificationChanged)

        self.updateRecentViewedNotes()
        notes = self.settings.recentViewedNotes()
        if len(notes) != 0:
            item = self.notesTree.pageToItem(notes[0])
            self.notesTree.setCurrentItem(item)

    def newNoteDisplay(self, item, anchor=None):
        msn = MikiSepNote(self.settings,
                          item.text(0),
                          self.notesTree.itemToFile(item),
                          plain_text=False,
                          parent=self)
        if anchor:
            msn.note_view.page().mainFrame().scrollToAnchor(anchor)
        msn.show()

    def newPlainTextNoteDisplay(self, item, anchor=None):
        msn = MikiSepNote(self.settings,
                          item.text(0),
                          self.notesTree.itemToFile(item),
                          plain_text=True,
                          parent=self)
        if anchor:
            item = msn.findItemByAnchor(anchor)[0]
            msn.tocNavigate(item)
        msn.show()

    def openFuncWrapper(self):
        self.openFunction(self.quickNoteNav.text())()

    def setupWhoosh(self):
        # Initialize whoosh index, make sure notePath/.indexdir exists
        indexdir = self.settings.indexdir
        try:
            self.ix = open_dir(indexdir)
        except:
            QDir().mkpath(indexdir)
            self.ix = create_in(indexdir, self.settings.schema)
            # Fork a process to update index, which benefit responsiveness.
            p = Thread(target=self.whoosh_index, args=())
            p.start()

    def restore(self):
        """ Restore saved geometry and state.
            Set the status of side panels in View Menu correspondently.
        """
        if self.settings.geometry:
            self.restoreGeometry(self.settings.geometry)
        if self.settings.windowstate:
            self.restoreState(self.settings.windowstate)

    def initTree(self, notePath, parent):
        ''' When there exist foo.md, foo.mkd, foo.markdown,
            only one item will be shown in notesTree.
        '''
        if not QDir(notePath).exists():
            return
        notebookDir = QDir(notePath)
        notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'],
                                              QDir.NoFilter,
                                              QDir.Name | QDir.IgnoreCase)
        nl = [note.completeBaseName() for note in notesList]
        noduplicate = list(set(nl))
        for name in noduplicate:
            item = QTreeWidgetItem(parent, [name])
            path = notePath + '/' + name
            self.initTree(path, item)

    def updateToc(self):
        ''' TOC is updated in `updateView`
            tocTree fields: [hdrText, hdrPosition, hdrAnchor]
        '''
        root = self.notesTree.currentPage()
        strip_math_for_header_parsing = False
        strip_fence_for_header_parsing = False
        if 'asciimathml' in self.settings.extensions:
            strip_math_for_header_parsing = True
        if 'fenced_code' in self.settings.extensions or 'extra' in self.settings.extensions:
            strip_fence_for_header_parsing = True
        self.tocTree.updateToc(
            root,
            parseHeaders(self.notesEdit.toPlainText(),
                         strip_fenced_block=strip_fence_for_header_parsing,
                         strip_ascii_math=strip_math_for_header_parsing))

    def updateAttachmentView(self):
        # Update attachmentView to show corresponding attachments.
        item = self.notesTree.currentItem()
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(item))
        self.attachmentView.setRootIndex(index)

    def openFile(self, filename):
        fh = QFile(filename)
        try:
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
        except IOError as e:
            QMessageBox.warning(
                self, self.tr('Read Error'),
                self.tr('Failed to open %s: %s') % (filename, e))
        finally:
            if fh is not None:
                noteBody = QTextStream(fh).readAll()
                fh.close()
                self.notesEdit.setPlainText(noteBody)
                self.notesView.scrollPosition = QPoint(0, 0)
                # self.actionSave.setEnabled(False)
                self.notesEdit.document().setModified(False)
                self.notesView.updateView()
                self.setCurrentNote()
                self.updateRecentViewedNotes()
                #self.statusLabel.setText(noteFullName)

    def currentItemChangedWrapper(self, current, previous):
        if current is None:
            return
        #if previous != None and self.notesTree.pageExists(previous):
        prev = self.notesTree.itemToPage(previous)
        if self.notesTree.pageExists(prev):
            self.saveNote(previous)

        currentFile = self.notesTree.itemToFile(current)
        self.openFile(currentFile)

        # Update attachmentView to show corresponding attachments.
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(current))
        self.attachmentView.setRootIndex(index)

    def tocNavigate(self, current):
        ''' works for notesEdit now '''
        if current is None:
            return
        pos = int(current.text(1))
        link = "file://" + self.notePath + "/#" + current.text(2)
        # Move cursor to END first will ensure
        # header is positioned at the top of visual area.
        self.notesEdit.moveCursor(QTextCursor.End)
        cur = self.notesEdit.textCursor()
        cur.setPosition(pos, QTextCursor.MoveAnchor)
        self.notesEdit.setTextCursor(cur)
        self.notesView.load(QUrl(link))

    def switchNote(self, num):
        if num < len(self.viewedListActions):
            self.viewedListActions[num].trigger()

    def saveCurrentNote(self):
        item = self.notesTree.currentItem()
        self.saveNote(item)

    def saveNote(self, item):
        if self.notesEdit.document().isModified():
            self.notesEdit.document().setModified(False)
        else:
            return
        self.notesEdit.save(item)

    def saveNoteAs(self):
        self.saveCurrentNote()
        fileName = QFileDialog.getSaveFileName(
            self, self.tr('Save as'), '',
            '(*.md *.mkd *.markdown);;' + self.tr('All files(*)'))
        if fileName == '':
            return
        if not QFileInfo(fileName).suffix():
            fileName += '.md'
        fh = QFile(fileName)
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << self.notesEdit.toPlainText()
        fh.close()

    def printNote(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setCreator(__appname__ + ' ' + __version__)
        printer.setDocName(self.notesTree.currentItem().text(0))
        printdialog = QPrintDialog(printer, self)
        if printdialog.exec() == QDialog.Accepted:
            self.notesView.print_(printer)

    def noteEditted(self):
        """ Continuously get fired while editing"""
        self.updateToc()
        self.notesView.updateLiveView()

    def modificationChanged(self, changed):
        """ Fired one time: modified or not """
        self.actions['save'].setEnabled(changed)
        name = self.notesTree.currentPage()
        self.statusBar.clearMessage()
        if changed:
            self.statusLabel.setText(name + '*')
        else:
            self.statusLabel.setText(name)

    def importPage(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr('Import file'), '',
            '(*.md *.mkd *.markdown *.txt);;' + self.tr('All files(*)'))
        if filename == '':
            return
        self.importPageCore(filename)

    def importPageCore(self, filename):
        fh = QFile(filename)
        fh.open(QIODevice.ReadOnly)
        fileBody = QTextStream(fh).readAll()
        fh.close()
        page = QFileInfo(filename).completeBaseName()
        fh = QFile(self.notesTree.pageToFile(page))
        if fh.exists():
            QMessageBox.warning(self, self.tr("Import Error"),
                                self.tr("Page already exists: %s") % page)
            dialog = LineEditDialog(self.notePath, self)
            if dialog.exec_():
                page = dialog.editor.text()
                fh.close()
                fh = QFile(self.notesTree.pageToFile(page))
            else:
                return
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << fileBody
        fh.close()
        item = QTreeWidgetItem(self.notesTree, [page])
        self.notesTree.sortItems(0, Qt.AscendingOrder)
        self.notesTree.setCurrentItem(item)

    def openNotebook(self):
        dialog = NotebookListDialog(self)
        if dialog.exec_():
            pass

    def notebookSettings(self):
        dialog = NotebookSettingsDialog(self)
        if dialog.exec_():
            pass

    def mikidownSettings(self):
        dialog = MikidownCfgDialog(self)
        if dialog.exec_():
            pass

    def reIndex(self):
        """ Whoosh index breaks for unknown reasons (sometimes) """
        shutil.rmtree(self.settings.indexdir)
        self.setupWhoosh()

    def act(self,
            name,
            trig,
            shortcut=None,
            checkable=False,
            icon=None,
            tooltip=None):
        """ A wrapper to several QAction methods """
        if icon:
            action = QAction(icon, name, self)
        else:
            action = QAction(name, self)
        if shortcut:
            action.setShortcut(QKeySequence(shortcut))
        action.setCheckable(checkable)
        if tooltip:
            action.setToolTip(tooltip)
        action.triggered.connect(trig)
        return action

    def edit(self, viewmode):
        """ Switch between EDIT and VIEW mode. """

        if self.actions['split'].isChecked():
            self.actions['split'].setChecked(False)
        self.notesView.setVisible(not viewmode)
        self.notesEdit.setVisible(viewmode)

        # Gives the keyboard input focus to notesEdit/notesView.
        # Without this, keyboard input may change note text even when
        # notesEdit is invisible.
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.saveCurrentNote()
        self.actions['insertImage'].setEnabled(viewmode)
        #self.actionLeftAndRight.setEnabled(True)
        #self.actionUpAndDown.setEnabled(True)

        # Render the note text as it is.
        self.notesView.updateView()

    def liveView(self, viewmode):
        """ Switch between VIEW and LIVE VIEW mode. """

        self.actions['split'].setChecked(viewmode)
        sizes = self.noteSplitter.sizes()
        if self.actions['edit'].isChecked():
            self.actions['edit'].setChecked(False)
            self.notesView.setVisible(viewmode)
            splitSize = [sizes[0] * 0.45, sizes[0] * 0.55]
        else:
            self.notesEdit.setVisible(viewmode)
            splitSize = [sizes[1] * 0.45, sizes[1] * 0.55]

        # setFocus for the same reason as in edit(self, viewmode)
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.actions['flipEditAndView'].setEnabled(viewmode)
        #self.actionUpAndDown.setEnabled(viewmode)
        self.actions['insertImage'].setEnabled(viewmode)
        self.noteSplitter.setSizes(splitSize)
        self.saveCurrentNote()

        # Render the note text as it is.
        self.notesView.updateView()

    def findBarVisibilityChanged(self, visible):
        self.actions['findText'].setChecked(visible)
        if visible:
            self.findEdit.setFocus(Qt.ShortcutFocusReason)

    def findText(self, back=False):
        flags = 0
        if back:
            flags = QTextDocument.FindBackward
        if self.checkBox.isChecked():
            flags = flags | QTextDocument.FindCaseSensitively
        text = self.findEdit.text()
        if not self.findMain(text, flags):
            if text in self.notesEdit.toPlainText():
                cursor = self.notesEdit.textCursor()
                if back:
                    cursor.movePosition(QTextCursor.End)
                else:
                    cursor.movePosition(QTextCursor.Start)
                self.notesEdit.setTextCursor(cursor)
                self.findMain(text, flags)
        # self.notesView.findText(text, flags)

    def findMain(self, text, flags):
        viewFlags = QWebPage.FindFlags(
            flags) | QWebPage.FindWrapsAroundDocument
        if flags:
            self.notesView.findText(text, viewFlags)
            return self.notesEdit.find(text, flags)
        else:
            self.notesView.findText(text)
            return self.notesEdit.find(text)

    def sortLines(self):
        ''' sort selected lines
            TODO: second sort reverse the order
        '''
        cursor = self.notesEdit.textCursor()
        start = cursor.selectionStart()
        end = cursor.selectionEnd()
        cursor.setPosition(start)
        cursor.movePosition(QTextCursor.StartOfLine)
        cursor.setPosition(end, mode=QTextCursor.KeepAnchor)
        cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor)
        text = cursor.selectedText()
        lines = text.split('\u2029')  # '\u2029' is the line break
        sortedLines = sorted(lines)
        cursor.insertText('\n'.join(sortedLines))

    def notesEditInFocus(self, e):
        if e.gotFocus:
            self.actions['insertImage'].setEnabled(True)
        # if e.lostFocus:
        #    self.actionInsertImage.setEnabled(False)

        # QWidget.focusInEvent(self,f)

    def searchNote(self):
        """ Sorting criteria: "title > path > content"
            Search matches are organized into html source.
        """

        pattern = self.searchEdit.text()
        if not pattern:
            return
        results = []
        print("Searching using", pattern)
        with self.ix.searcher() as searcher:
            matches = []
            queryp = QueryParser("content", self.ix.schema)
            #allow escaped qutoes when regex searching
            queryp.add_plugin(
                RegexPlugin(expr=r'r"(?P<text>[^"\\]*(\\.[^"\\]*)*)"'))
            # ~~r"pattern" is the desired regex term format~~ Don't autoforce regexing
            query = queryp.parse(pattern)
            #print("durp durp", query)
            ms = searcher.search(query, limit=None)  # default limit is 10!
            for m in ms:
                #if not m in matches:
                matches.append(m)

            for r in matches:
                title = r['title']
                path = r['path']
                term = r.highlights("content")
                results.append([title, path, term])

            html = ""
            for title, path, hi in results:
                html += ("<p><a href='" + path + "'>" + title +
                         "</a><br/><span class='path'>" + path +
                         "</span><br/>" + hi + "</p>")
            self.searchView.setHtml(html)
            print("Finished searching", pattern)

    def whoosh_index(self):
        it = QTreeWidgetItemIterator(self.notesTree,
                                     QTreeWidgetItemIterator.All)
        print("Starting complete indexing.")
        #writer = self.ix.writer()
        writer = AsyncWriter(self.ix)
        while it.value():
            treeItem = it.value()
            name = self.notesTree.itemToPage(treeItem)
            path = os.path.join(self.notesTree.pageToFile(name)).replace(
                os.sep, '/')
            print(path)
            fileobj = open(path, 'r', encoding='utf-8')
            content = fileobj.read()
            fileobj.close()
            if METADATA_CHECKER.match(
                    content) and 'meta' in self.settings.extensions:
                no_metadata_content = METADATA_CHECKER.sub("",
                                                           content,
                                                           count=1).lstrip()
                self.settings.md.reset().convert(content)
                writer.update_document(
                    path=name,
                    title=parseTitle(content, name),
                    content=no_metadata_content,
                    tags=','.join(self.settings.md.Meta.get('tags',
                                                            [])).strip())
            else:
                writer.add_document(path=name,
                                    title=parseTitle(content, name),
                                    content=content,
                                    tags='')

            it += 1
        writer.commit()
        print("Finished completely reindexing.")

    def listItemChanged(self, row):
        if row != -1:
            item = self.searchList.currentItem().data(Qt.UserRole)
            self.notesTree.setCurrentItem(item)
            flags = QWebPage.HighlightAllOccurrences
            self.notesView.findText(self.searchEdit.text(), flags)

    def setCurrentNote(self):
        item = self.notesTree.currentItem()
        name = self.notesTree.itemToPage(item)

        # Current note is inserted to head of list.
        notes = self.settings.recentViewedNotes()
        for f in notes:
            if f == name:
                notes.remove(f)
        notes.insert(0, name)

        recent_notes_n = Mikibook.settings.value('recentNotesNumber',
                                                 type=int,
                                                 defaultValue=20)
        if len(notes) > recent_notes_n:
            del notes[recent_notes_n:]
        self.settings.updateRecentViewedNotes(notes)

    def updateRecentViewedNotes(self):
        """ Switching notes will trigger this.
            When Alt pressed, show note number.
        """

        self.viewedList.clear()
        self.viewedListActions = []

        # Check notes exists.
        viewedNotes = self.settings.recentViewedNotes()
        existedNotes = []
        i = 0
        for f in viewedNotes:
            if self.notesTree.pageExists(f):
                existedNotes.append(f)
                names = f.split('/')
                if self.altPressed and i in range(1, 10):
                    action = self.act(names[-1], self.openFunction(f),
                                      'Alt+' + str(i), True, ViewedNoteIcon(i),
                                      'Alt+' + str(i))
                else:
                    action = self.act(names[-1], self.openFunction(f), None,
                                      True)
                self.viewedListActions.append(action)
                i += 1

        if not self.altPressed:
            self.settings.updateRecentViewedNotes(existedNotes)
        for action in self.viewedListActions:
            self.viewedList.addAction(action)
        if len(self.viewedListActions):
            self.viewedListActions[0].setChecked(True)

    def openFunction(self, name):
        item = self.notesTree.pageToItem(name)
        return lambda: self.notesTree.setCurrentItem(item)

    def raiseDock(self, widget):
        if not widget.isVisible():
            widget.show()
        if widget == self.dockSearch:
            self.searchEdit.setFocus()
        widget.raise_()

    def flipEditAndView(self):
        index = self.noteSplitter.indexOf(self.notesEdit)
        if index == 0:
            self.noteSplitter.insertWidget(1, self.notesEdit)
        else:
            self.noteSplitter.insertWidget(0, self.notesEdit)

    def leftAndRight(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Horizontal)
        #self.actionLeftAndRight.setEnabled(False)
        #self.actionUpAndDown.setEnabled(True)

    def upAndDown(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Vertical)
        #self.actionUpAndDown.setEnabled(False)
        #self.actionLeftAndRight.setEnabled(True)

    def readmeHelp(self):
        readmeFile = '/usr/share/mikidown/README.mkd'
        if not os.path.exists(readmeFile):
            readmeFile = os.path.join(
                os.path.dirname(os.path.dirname(__file__)),
                'README.mkd').replace(os.sep, '/')
        self.importPageCore(readmeFile)

    def changelogHelp(self):
        changeLog = "/usr/share/mikidown/Changelog.md"
        if not os.path.exists(changeLog):
            changeLog = os.path.join(
                os.path.dirname(os.path.dirname(__file__)),
                'Changelog.md').replace(os.sep, '/')
        self.importPageCore(changeLog)

    def keyPressEvent(self, event):
        """ When Alt pressed, note number will be shown in viewedList. """
        if event.key() == Qt.Key_Alt:
            self.altPressed = True
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Alt:
            self.altPressed = False
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def closeEvent(self, event):
        """
            saveGeometry: Saves the current geometry and state for
                          top-level widgets
            saveState: Restores the state of this mainwindow's toolbars
                       and dockwidgets
        """
        self.saveCurrentNote()
        self.ix.close()
        self.notesEdit.ix.close()
        if hasattr(self.notesTree, 'ix'):
            self.notesTree.ix.close()
        self.settings.saveGeometry(self.saveGeometry())
        self.settings.saveWindowState(self.saveState())
        event.accept()
        os.close(self.lockPathFH)
        lockPath = os.path.join(self.settings.notebookPath, '.mikidown_lock')
        os.remove(lockPath)
Esempio n. 6
0
class MikiWindow(QMainWindow):
    def __init__(self, settings, parent=None):
        super(MikiWindow, self).__init__(parent)
        self.setObjectName("mikiWindow")
        self.settings = settings
        self.notePath = settings.notePath

        ################ Setup core components ################
        self.notesTree = MikiTree(self)
        self.quickNoteNav = QLineEdit()
        self.notesTab = QWidget()
        self.completer = SlashPleter()
        self.completer.setModel(self.notesTree.model())
        self.quickNoteNav.setCompleter(self.completer)
        self.notesTree.setObjectName("notesTree")
        self.initTree(self.notePath, self.notesTree)
        self.notesTree.sortItems(0, Qt.AscendingOrder)

        self.ix = None
        self.setupWhoosh()

        self.viewedList = QToolBar(self.tr('Recently Viewed'), self)
        self.viewedList.setIconSize(QSize(16, 16))
        self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.viewedListActions = []
        self.noteSplitter = QSplitter(Qt.Horizontal)

        self.dockIndex = QDockWidget("Index")
        self.dockSearch = QDockWidget("Search")
        self.searchEdit = QLineEdit()
        self.searchView = MikiSearch(self)
        self.searchTab = QWidget()
        self.dockToc = QDockWidget("TOC")
        self.tocTree = TocTree()
        self.dockAttachment = QDockWidget("Attachment")
        self.attachmentView = AttachmentView(self)

        self.notesEdit = MikiEdit(self)
        self.notesEdit.setObjectName("notesEdit")
        MikiHighlighter(self.notesEdit)
        self.notesView = MikiView(self)

        self.findBar = QToolBar(self.tr('Find'), self)
        self.findBar.setFixedHeight(30)
        self.findEdit = QLineEdit(self.findBar)
        self.checkBox = QCheckBox(self.tr('Match case'), self.findBar)

        self.statusBar = QStatusBar(self)
        self.statusLabel = QLabel(self)

        self.altPressed = False


        ################ Setup actions ################
        self.actions = dict()
        self.setupActions()


        ################ Setup mainwindow ################
        self.setupMainWindow()

        # show changelogs after upgrade mikidown
        if self.settings.version < __version__:
            self.changelogHelp()
            self.settings.qsettings.setValue("version", __version__)


    def setupActions(self):

        # Global Actions
        actTabIndex = self.act(self.tr('Switch to Index Tab'),
            lambda: self.raiseDock(self.dockIndex), 'Ctrl+Shift+I')
        actTabSearch = self.act(self.tr('Switch to Search Tab'),
            lambda: self.raiseDock(self.dockSearch), 'Ctrl+Shift+F')
        self.addAction(actTabIndex)
        self.addAction(actTabSearch)

        ################ Menu Actions ################
        # actions in menuFile
        actionNewPage = self.act(self.tr('&New Page...'),
            self.notesTree.newPage, QKeySequence.New)
        self.actions.update(newPage=actionNewPage)

        actionNewSubpage = self.act(self.tr('New Sub&page...'),
            self.notesTree.newSubpage, 'Ctrl+Shift+N')
        self.actions.update(newSubpage=actionNewSubpage)

        actionImportPage = self.act(self.tr('&Import Page...'), self.importPage)
        self.actions.update(importPage=actionImportPage)

        actionNBSettings = self.act(self.tr('Notebook Set&tings...'), self.notebookSettings)
        self.actions.update(NBSettings=actionNBSettings)

        actionMDSettings = self.act(self.tr('&Mikidown Settings...'), self.mikidownSettings)
        self.actions.update(MDSettings=actionMDSettings)

        actionOpenNotebook = self.act(self.tr('&Open Notebook...'),
            self.openNotebook, QKeySequence.Open)
        self.actions.update(openNotebook=actionOpenNotebook)

        actionReIndex = self.act(self.tr('Re-index'), self.reIndex)
        self.actions.update(reIndex=actionReIndex)

        actionSave = self.act(self.tr('&Save'),
            self.saveCurrentNote, QKeySequence.Save)
        actionSave.setEnabled(False)
        self.actions.update(save=actionSave)

        actionSaveAs = self.act(self.tr('Save &As...'),
            self.saveNoteAs, QKeySequence.SaveAs)
        self.actions.update(saveAs=actionSaveAs)

        actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml)
        self.actions.update(html=actionHtml)

        actionPrint = self.act(self.tr('&Print'),
            self.printNote, QKeySequence.Print)
        self.actions.update(print_=actionPrint)

        actionRenamePage = self.act(self.tr('&Rename Page...'),
            self.notesTree.renamePage, 'F2')
        self.actions.update(renamePage=actionRenamePage)

        actionDelPage = self.act(self.tr('&Delete Page'),
            self.notesTree.delPageWrapper, QKeySequence.Delete)
        self.actions.update(delPage=actionDelPage)

        actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit)
        actionQuit.setMenuRole(QAction.QuitRole)
        self.actions.update(quit=actionQuit)

        # actions in menuEdit
        actionUndo = self.act(self.tr('&Undo'),
            lambda: self.notesEdit.undo(), QKeySequence.Undo)
        actionUndo.setEnabled(False)
        self.notesEdit.undoAvailable.connect(actionUndo.setEnabled)
        self.actions.update(undo=actionUndo)

        actionRedo = self.act(self.tr('&Redo'),
            lambda: self.notesEdit.redo(), QKeySequence.Redo)
        actionRedo.setEnabled(False)
        self.notesEdit.redoAvailable.connect(actionRedo.setEnabled)
        self.actions.update(redo=actionRedo)

        actionFindText = self.act(self.tr('&Find Text'),
            self.findBar.setVisible, QKeySequence.Find, True)
        self.actions.update(findText=actionFindText)

        actionFind = self.act(self.tr('Next'),
            self.findText, QKeySequence.FindNext)
        self.actions.update(find=actionFind)

        actionFindPrev = self.act(self.tr('Previous'),
            lambda: self.findText(back=True), QKeySequence.FindPrevious)
        self.actions.update(findPrev=actionFindPrev)

        actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines)
        self.actions.update(sortLines=actionSortLines)

        actionQuickNav = self.act(self.tr("&Quick Open Note"),
                        self.quickNoteNav.setFocus, 'Ctrl+G')
        self.addAction(actionQuickNav)

        actionInsertImage = self.act(self.tr('&Insert Attachment'),
            self.notesEdit.insertAttachmentWrapper, 'Ctrl+I')
        actionInsertImage.setEnabled(False)
        self.actions.update(insertImage=actionInsertImage)

        # actions in menuView
        actionEdit = self.act(self.tr('Edit'), self.edit, 'Ctrl+E',
            True, QIcon(':/icons/edit.svg'), 'Edit mode (Ctrl+E)')
        self.actions.update(edit=actionEdit)

        actionSplit = self.act(self.tr('Split'), self.liveView, 'Ctrl+R',
            True, QIcon(':/icons/split.svg'), 'Split mode (Ctrl+R)')
        self.actions.update(split=actionSplit)

        actionFlipEditAndView = self.act(self.tr('Flip Edit and View'),
            self.flipEditAndView)
        actionFlipEditAndView.setEnabled(False)
        self.actions.update(flipEditAndView=actionFlipEditAndView)

        #actionLeftAndRight = self.act(
        #    self.tr('Split into Left and Right'), trig=self.leftAndRight)
        #actionUpAndDown = self.act(
        #    self.tr('Split into Up and Down'), trig=self.upAndDown)
        # self.actionLeftAndRight.setEnabled(False)
        # self.actionUpAndDown.setEnabled(False)

        # actions in menuHelp
        actionReadme = self.act(self.tr('README'), self.readmeHelp)
        self.actions.update(readme=actionReadme)

        actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp)
        self.actions.update(changelog=actionChangelog)

        actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt)
        self.actions.update(aboutQt=actionAboutQt)


    def setupMainWindow(self):
        self.resize(800, 600)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((
            screen.width()-size.width())/2, (screen.height()-size.height())/2)
        self.setWindowTitle(
            '{} - {}'.format(self.settings.notebookName, __appname__))

        self.viewedList.setFixedHeight(25)
        self.noteSplitter.addWidget(self.notesEdit)
        self.noteSplitter.addWidget(self.notesView)
        mainSplitter = QSplitter(Qt.Vertical)
        mainSplitter.setChildrenCollapsible(False)
        mainSplitter.addWidget(self.viewedList)
        mainSplitter.addWidget(self.noteSplitter)
        mainSplitter.addWidget(self.findBar)
        self.setCentralWidget(mainSplitter)

        self.searchEdit.returnPressed.connect(self.searchNote)
        self.quickNoteNav.returnPressed.connect(self.openFuncWrapper)
        searchLayout = QVBoxLayout()
        searchLayout.addWidget(self.searchEdit)
        searchLayout.addWidget(self.searchView)
        self.searchTab.setLayout(searchLayout)
        self.tocTree.header().close()

        indexLayout = QVBoxLayout(self.notesTab)
        indexLayout.addWidget(self.quickNoteNav)
        indexLayout.addWidget(self.notesTree)

        self.dockIndex.setObjectName("Index")
        self.dockIndex.setWidget(self.notesTab)
        self.dockSearch.setObjectName("Search")
        self.dockSearch.setWidget(self.searchTab)
        self.dockToc.setObjectName("TOC")
        self.dockToc.setWidget(self.tocTree)
        self.dockAttachment.setObjectName("Attachment")
        self.dockAttachment.setWidget(self.attachmentView)

        self.setDockOptions(QMainWindow.VerticalTabs)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment)
        self.tabifyDockWidget(self.dockIndex, self.dockSearch)
        self.tabifyDockWidget(self.dockSearch, self.dockToc)
        self.tabifyDockWidget(self.dockToc, self.dockAttachment)
        self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North)
        self.dockIndex.raise_()      # Put dockIndex on top of the tab stack

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        menuFile = menuBar.addMenu(self.tr('&File'))
        menuEdit = menuBar.addMenu(self.tr('&Edit'))
        menuView = menuBar.addMenu(self.tr('&View'))
        menuHelp = menuBar.addMenu(self.tr('&Help'))
        # menuFile
        menuFile.addAction(self.actions['newPage'])
        menuFile.addAction(self.actions['newSubpage'])
        menuFile.addAction(self.actions['NBSettings'])
        menuFile.addAction(self.actions['MDSettings'])
        menuFile.addAction(self.actions['importPage'])
        menuFile.addAction(self.actions['openNotebook'])
        menuFile.addAction(self.actions['reIndex'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['save'])
        menuFile.addAction(self.actions['saveAs'])
        menuFile.addAction(self.actions['print_'])
        menuExport = menuFile.addMenu(self.tr('&Export'))
        menuExport.addAction(self.actions['html'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['renamePage'])
        menuFile.addAction(self.actions['delPage'])
        menuFile.addSeparator()
        menuFile.addAction(self.actions['quit'])
        # menuEdit
        menuEdit.addAction(self.actions['undo'])
        menuEdit.addAction(self.actions['redo'])
        menuEdit.addAction(self.actions['findText'])
        menuEdit.addSeparator()
        menuEdit.addAction(self.actions['sortLines'])
        menuEdit.addAction(self.actions['insertImage'])
        # menuView
        menuView.addAction(self.actions['edit'])
        menuView.addAction(self.actions['split'])
        menuView.addAction(self.actions['flipEditAndView'])
        menuShowHide = menuView.addMenu(self.tr('Show/Hide'))
        menuShowHide.addAction(self.dockIndex.toggleViewAction())
        menuShowHide.addAction(self.dockSearch.toggleViewAction())
        menuShowHide.addAction(self.dockToc.toggleViewAction())
        menuShowHide.addAction(self.dockAttachment.toggleViewAction())
        #menuMode = menuView.addMenu(self.tr('Mode'))
        #menuMode.addAction(self.actionLeftAndRight)
        #menuMode.addAction(self.actionUpAndDown)
        # menuHelp
        menuHelp.addAction(self.actions['readme'])
        menuHelp.addAction(self.actions['changelog'])
        menuHelp.addAction(self.actions['aboutQt'])

        toolBar = QToolBar(self.tr("toolbar"), self)
        toolBar.setObjectName("toolbar")       # needed in saveState()
        toolBar.setIconSize(QSize(16, 16))
        toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.addToolBar(Qt.TopToolBarArea, toolBar)
        toolBar.addAction(self.actions['edit'])
        toolBar.addAction(self.actions['split'])
        self.findEdit.returnPressed.connect(self.findText)
        self.findBar.addWidget(self.findEdit)
        self.findBar.addWidget(self.checkBox)
        self.findBar.addAction(self.actions['findPrev'])
        self.findBar.addAction(self.actions['find'])
        self.findBar.setVisible(False)
        self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged)

        self.setStatusBar(self.statusBar)
        self.statusBar.addWidget(self.statusLabel, 1)

        self.notesTree.currentItemChanged.connect(
            self.currentItemChangedWrapper)
        self.tocTree.itemClicked.connect(self.tocNavigate)
        self.notesEdit.textChanged.connect(self.noteEditted)

        self.notesEdit.document(
        ).modificationChanged.connect(self.modificationChanged)

        self.updateRecentViewedNotes()
        notes = self.settings.recentViewedNotes()
        if len(notes) != 0:
            item = self.notesTree.pageToItem(notes[0])
            self.notesTree.setCurrentItem(item)

    def openFuncWrapper(self):
        self.openFunction(self.quickNoteNav.text())()

    def setupWhoosh(self):
        # Initialize whoosh index, make sure notePath/.indexdir exists
        indexdir = self.settings.indexdir
        try:
            self.ix = open_dir(indexdir)
        except:
            QDir().mkpath(indexdir)
            self.ix = create_in(indexdir, self.settings.schema)
            # Fork a process to update index, which benefit responsiveness.
            p = Thread(target=self.whoosh_index, args=())
            p.start()


    def restore(self):
        """ Restore saved geometry and state.
            Set the status of side panels in View Menu correspondently.
        """
        if self.settings.geometry:
            self.restoreGeometry(self.settings.geometry)
        if self.settings.windowstate:
            self.restoreState(self.settings.windowstate)

    def initTree(self, notePath, parent):
        ''' When there exist foo.md, foo.mkd, foo.markdown,
            only one item will be shown in notesTree.
        '''
        if not QDir(notePath).exists():
            return
        notebookDir = QDir(notePath)
        notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'],
                                               QDir.NoFilter,
                                               QDir.Name|QDir.IgnoreCase)
        nl = [note.completeBaseName() for note in notesList]
        noduplicate = list(set(nl))
        for name in noduplicate:
            item = QTreeWidgetItem(parent, [name])
            path = notePath + '/' + name
            self.initTree(path, item)

    def updateToc(self):
        ''' TOC is updated in `updateView`
            tocTree fields: [hdrText, hdrPosition, hdrAnchor]
        '''
        root = self.notesTree.currentPage()
        self.tocTree.clear()
        item = QTreeWidgetItem(self.tocTree, [root, '0'])
        curLevel = 0
        for (level, h, p, a) in parseHeaders(self.notesEdit.toPlainText()):
            val = [h, str(p), a]
            if level == curLevel:
                item = QTreeWidgetItem(item.parent(), val)
            elif level < curLevel:
                item = QTreeWidgetItem(item.parent().parent(), val)
                curLevel = level
            else:
                item = QTreeWidgetItem(item, val)
                curLevel = level
        self.tocTree.expandAll()

    def updateAttachmentView(self):
        # Update attachmentView to show corresponding attachments.
        item = self.notesTree.currentItem()
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(item))
        self.attachmentView.setRootIndex(index)

    def openFile(self, filename):
        fh = QFile(filename)
        try:
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(fh.errorString())
        except IOError as e:
            QMessageBox.warning(self, 'Read Error',
                                'Failed to open %s: %s' % (filename, e))
        finally:
            if fh is not None:
                noteBody = QTextStream(fh).readAll()
                fh.close()
                self.notesEdit.setPlainText(noteBody)
                self.notesView.scrollPosition = QPoint(0, 0)
                # self.actionSave.setEnabled(False)
                self.notesEdit.document().setModified(False)
                self.notesView.updateView()
                self.setCurrentNote()
                self.updateRecentViewedNotes()
                #self.statusLabel.setText(noteFullName)

    def currentItemChangedWrapper(self, current, previous):
        if current is None:
            return
        #if previous != None and self.notesTree.pageExists(previous):
        prev = self.notesTree.itemToPage(previous)
        if self.notesTree.pageExists(prev):
            self.saveNote(previous)

        currentFile = self.notesTree.itemToFile(current)
        self.openFile(currentFile)

        # Update attachmentView to show corresponding attachments.
        index = self.attachmentView.model.index(
            self.notesTree.itemToAttachmentDir(current))
        self.attachmentView.setRootIndex(index)

    def tocNavigate(self, current):
        ''' works for notesEdit now '''
        if current is None:
            return
        pos = int(current.text(1))
        link = "file://" + self.notePath + "/#" + current.text(2)
        # Move cursor to END first will ensure
        # header is positioned at the top of visual area.
        self.notesEdit.moveCursor(QTextCursor.End)
        cur = self.notesEdit.textCursor()
        cur.setPosition(pos, QTextCursor.MoveAnchor)
        self.notesEdit.setTextCursor(cur)
        self.notesView.load(QUrl(link))

    def switchNote(self, num):
        if num < len(self.viewedListActions):
            self.viewedListActions[num].trigger()

    def saveCurrentNote(self):
        item = self.notesTree.currentItem()
        self.saveNote(item)

    def saveNote(self, item):
        if self.notesEdit.document().isModified():
            self.notesEdit.document().setModified(False)
        else:
            return
        self.notesEdit.save(item)

    def saveNoteAs(self):
        self.saveCurrentNote()
        fileName = QFileDialog.getSaveFileName(self, self.tr('Save as'), '',
            '(*.md *.mkd *.markdown);;'+self.tr('All files(*)'))
        if fileName == '':
            return
        if not QFileInfo(fileName).suffix():
            fileName += '.md'
        fh = QFile(fileName)
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << self.notesEdit.toPlainText()
        fh.close()

    def printNote(self):
        printer = QPrinter(QPrinter.HighResolution)
        printer.setCreator(__appname__ + ' ' + __version__)
        printer.setDocName(self.notesTree.currentItem().text(0))
        printdialog = QPrintDialog(printer, self)
        if printdialog.exec() == QDialog.Accepted:
            self.notesView.print_(printer)

    def noteEditted(self):
        """ Continuously get fired while editing"""
        self.updateToc()
        self.notesView.updateLiveView()

    def modificationChanged(self, changed):
        """ Fired one time: modified or not """
        self.actions['save'].setEnabled(changed)
        name = self.notesTree.currentPage()
        self.statusBar.clearMessage()
        if changed:
            self.statusLabel.setText(name + '*')
        else:
            self.statusLabel.setText(name)

    def importPage(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr('Import file'), '',
            '(*.md *.mkd *.markdown *.txt);;'+self.tr('All files(*)'))
        if filename == '':
            return
        self.importPageCore(filename)

    def importPageCore(self, filename):
        fh = QFile(filename)
        fh.open(QIODevice.ReadOnly)
        fileBody = QTextStream(fh).readAll()
        fh.close()
        page = QFileInfo(filename).completeBaseName()
        fh = QFile(self.notesTree.pageToFile(page))
        if fh.exists():
            QMessageBox.warning(self, 'Import Error',
                'Page already exists: %s' % page)
            dialog = LineEditDialog(self.notePath, self)
            if dialog.exec_():
                page = dialog.editor.text()
                fh.close()
                fh = QFile(self.notesTree.pageToFile(page))
            else:
                return
        fh.open(QIODevice.WriteOnly)
        savestream = QTextStream(fh)
        savestream << fileBody
        fh.close()
        item = QTreeWidgetItem(self.notesTree, [page])
        self.notesTree.sortItems(0, Qt.AscendingOrder)
        self.notesTree.setCurrentItem(item)

    def openNotebook(self):
        dialog = NotebookListDialog(self)
        if dialog.exec_():
            pass

    def notebookSettings(self):
        dialog = NotebookSettingsDialog(self)
        if dialog.exec_():
            pass

    def mikidownSettings(self):
        dialog = MikidownCfgDialog(self)
        if dialog.exec_():
            pass


    def reIndex(self):
        """ Whoosh index breaks for unknown reasons (sometimes) """
        shutil.rmtree(self.settings.indexdir)
        self.setupWhoosh()

    def act(self, name, trig, shortcut=None, checkable=False,
            icon=None, tooltip=None):
        """ A wrapper to several QAction methods """
        if icon:
            action = QAction(icon, name, self)
        else:
            action = QAction(name, self)
        if shortcut:
            action.setShortcut(QKeySequence(shortcut))
        action.setCheckable(checkable)
        if tooltip:
            action.setToolTip(tooltip)
        action.triggered.connect(trig)
        return action

    def edit(self, viewmode):
        """ Switch between EDIT and VIEW mode. """

        if self.actions['split'].isChecked():
            self.actions['split'].setChecked(False)
        self.notesView.setVisible(not viewmode)
        self.notesEdit.setVisible(viewmode)

        # Gives the keyboard input focus to notesEdit/notesView.
        # Without this, keyboard input may change note text even when
        # notesEdit is invisible.
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.saveCurrentNote()
        self.actions['insertImage'].setEnabled(viewmode)
        #self.actionLeftAndRight.setEnabled(True)
        #self.actionUpAndDown.setEnabled(True)

        # Render the note text as it is.
        self.notesView.updateView()

    def liveView(self, viewmode):
        """ Switch between VIEW and LIVE VIEW mode. """

        self.actions['split'].setChecked(viewmode)
        sizes = self.noteSplitter.sizes()
        if self.actions['edit'].isChecked():
            self.actions['edit'].setChecked(False)
            self.notesView.setVisible(viewmode)
            splitSize = [sizes[0]*0.45, sizes[0]*0.55]
        else:
            self.notesEdit.setVisible(viewmode)
            splitSize = [sizes[1]*0.45, sizes[1]*0.55]

        # setFocus for the same reason as in edit(self, viewmode)
        if viewmode:
            self.notesEdit.setFocus()
        else:
            self.notesView.setFocus()

        self.actions['flipEditAndView'].setEnabled(viewmode)
        #self.actionUpAndDown.setEnabled(viewmode)
        self.actions['insertImage'].setEnabled(viewmode)
        self.noteSplitter.setSizes(splitSize)
        self.saveCurrentNote()

        # Render the note text as it is.
        self.notesView.updateView()

    def findBarVisibilityChanged(self, visible):
        self.actions['findText'].setChecked(visible)
        if visible:
            self.findEdit.setFocus(Qt.ShortcutFocusReason)

    def findText(self, back=False):
        flags = 0
        if back:
            flags = QTextDocument.FindBackward
        if self.checkBox.isChecked():
            flags = flags | QTextDocument.FindCaseSensitively
        text = self.findEdit.text()
        if not self.findMain(text, flags):
            if text in self.notesEdit.toPlainText():
                cursor = self.notesEdit.textCursor()
                if back:
                    cursor.movePosition(QTextCursor.End)
                else:
                    cursor.movePosition(QTextCursor.Start)
                self.notesEdit.setTextCursor(cursor)
                self.findMain(text, flags)
        # self.notesView.findText(text, flags)

    def findMain(self, text, flags):
        viewFlags = QWebPage.FindFlags(
            flags) | QWebPage.FindWrapsAroundDocument
        if flags:
            self.notesView.findText(text, viewFlags)
            return self.notesEdit.find(text, flags)
        else:
            self.notesView.findText(text)
            return self.notesEdit.find(text)

    def sortLines(self):
        ''' sort selected lines
            TODO: second sort reverse the order
        '''
        cursor = self.notesEdit.textCursor()
        start = cursor.selectionStart()
        end = cursor.selectionEnd()
        cursor.setPosition(start)
        cursor.movePosition(QTextCursor.StartOfLine)
        cursor.setPosition(end, mode=QTextCursor.KeepAnchor)
        cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor)
        text = cursor.selectedText()
        lines = text.split('\u2029')      # '\u2029' is the line break
        sortedLines = sorted(lines)
        cursor.insertText('\n'.join(sortedLines))

    def notesEditInFocus(self, e):
        if e.gotFocus:
            self.actions['insertImage'].setEnabled(True)
        # if e.lostFocus:
        #    self.actionInsertImage.setEnabled(False)

        # QWidget.focusInEvent(self,f)

    def searchNote(self):
        """ Sorting criteria: "title > path > content"
            Search matches are organized into html source.
        """

        pattern = self.searchEdit.text()
        if not pattern:
            return
        results = []
        print("Searching using", pattern)
        with self.ix.searcher() as searcher:
            matches = []
            for f in ["title", "path", "content"]:
                queryp = QueryParser(f, self.ix.schema)
                queryp.add_plugin(RegexPlugin())
                # r"pattern" is the desired regex term format
                query = queryp.parse('r"' + pattern + '"')
                ms = searcher.search(query, limit=None) # default limit is 10!
                for m in ms:
                    if not m in matches:
                        matches.append(m)

            for r in matches:
                title = r['title']
                path = r['path']
                term = r.highlights("content")
                results.append([title, path, term])

            html = ""
            for title, path, hi in results:
                html += ("<p><a href='" + path + "'>" + title +
                         "</a><br/><span class='path'>" +
                         path + "</span><br/>" + hi + "</p>")
            self.searchView.setHtml(html)
            print("Finished searching", pattern)

    def whoosh_index(self):
        it = QTreeWidgetItemIterator(
            self.notesTree, QTreeWidgetItemIterator.All)
        print("Starting complete indexing.")
        writer = self.ix.writer()
        while it.value():
            treeItem = it.value()
            name = self.notesTree.itemToPage(treeItem)
            path = os.path.join(self.notesTree.pageToFile(name)).replace(os.sep, '/')
            print(path)
            fileobj = open(path, 'r')
            content = fileobj.read()
            fileobj.close()
            writer.add_document(
                path=name, title=parseTitle(content, name), content=content)
            it += 1
        writer.commit()
        print("Finished completely reindexing.")

    def listItemChanged(self, row):
        if row != -1:
            item = self.searchList.currentItem().data(Qt.UserRole)
            self.notesTree.setCurrentItem(item)
            flags = QWebPage.HighlightAllOccurrences
            self.notesView.findText(self.searchEdit.text(), flags)

    def setCurrentNote(self):
        item = self.notesTree.currentItem()
        name = self.notesTree.itemToPage(item)

        # Current note is inserted to head of list.
        notes = self.settings.recentViewedNotes()
        for f in notes:
            if f == name:
                notes.remove(f)
        notes.insert(0, name)

        recent_notes_n = Mikibook.settings.value('recentNotesNumber',type=int, defaultValue=20)
        if len(notes) > recent_notes_n:
            del notes[recent_notes_n:]
        self.settings.updateRecentViewedNotes(notes)

    def updateRecentViewedNotes(self):
        """ Switching notes will trigger this.
            When Alt pressed, show note number.
        """

        self.viewedList.clear()
        self.viewedListActions = []

        # Check notes exists.
        viewedNotes = self.settings.recentViewedNotes()
        existedNotes = []
        i = 0
        for f in viewedNotes:
            if self.notesTree.pageExists(f):
                existedNotes.append(f)
                names = f.split('/')
                if self.altPressed and i in range(1, 10):
                    action = self.act(names[-1], self.openFunction(f),
                        'Alt+'+str(i), True, ViewedNoteIcon(i), 'Alt+'+str(i))
                else:
                    action = self.act(names[-1], self.openFunction(f),
                        None, True)
                self.viewedListActions.append(action)
                i += 1

        if not self.altPressed:
            self.settings.updateRecentViewedNotes(existedNotes)
        for action in self.viewedListActions:
            self.viewedList.addAction(action)
        if len(self.viewedListActions):
            self.viewedListActions[0].setChecked(True)

    def openFunction(self, name):
        item = self.notesTree.pageToItem(name)
        return lambda: self.notesTree.setCurrentItem(item)

    def raiseDock(self, widget):
        if not widget.isVisible():
            widget.show()
        if widget == self.dockSearch:
            self.searchEdit.setFocus()
        widget.raise_()

    def flipEditAndView(self):
        index = self.noteSplitter.indexOf(self.notesEdit)
        if index == 0:
            self.noteSplitter.insertWidget(1, self.notesEdit)
        else:
            self.noteSplitter.insertWidget(0, self.notesEdit)

    def leftAndRight(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Horizontal)
        #self.actionLeftAndRight.setEnabled(False)
        #self.actionUpAndDown.setEnabled(True)

    def upAndDown(self):
        self.liveView(True)
        self.noteSplitter.setOrientation(Qt.Vertical)
        #self.actionUpAndDown.setEnabled(False)
        #self.actionLeftAndRight.setEnabled(True)

    def readmeHelp(self):
        readmeFile = '/usr/share/mikidown/README.mkd'
        if not os.path.exists(readmeFile):
            readmeFile = os.path.join(
                os.path.dirname(os.path.dirname(__file__)), 'README.mkd').replace(os.sep, '/')
        self.importPageCore(readmeFile)

    def changelogHelp(self):
        changeLog = "/usr/share/mikidown/Changelog.md"
        if not os.path.exists(changeLog):
            changeLog = os.path.join(
                os.path.dirname(os.path.dirname(__file__)), 'Changelog.md').replace(os.sep, '/')
        self.importPageCore(changeLog)

    def keyPressEvent(self, event):
        """ When Alt pressed, note number will be shown in viewedList. """
        if event.key() == Qt.Key_Alt:
            self.altPressed = True
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Alt:
            self.altPressed = False
            self.updateRecentViewedNotes()
        else:
            QMainWindow.keyPressEvent(self, event)

    def closeEvent(self, event):
        """
            saveGeometry: Saves the current geometry and state for
                          top-level widgets
            saveState: Restores the state of this mainwindow's toolbars
                       and dockwidgets
        """
        self.saveCurrentNote()
        self.settings.saveGeometry(self.saveGeometry())
        self.settings.saveWindowState(self.saveState())
        event.accept()
Esempio n. 7
0
File: help.py Progetto: kzwkt/dff
class Help(QDockWidget):
    def __init__(self, parent=None, path=None):
        QDockWidget.__init__(self, parent)
        self.name = self.tr("Help")
        self.setFloating(False)
        self.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.__mainWidget = QSplitter(Qt.Horizontal)
        self.__uname = QWidget()

        mainWidgetLayout = QVBoxLayout(self.__uname)
        mainWidgetLayout.setContentsMargins(0, 0, 0, 0)

        # create helper + search engine
        self.__helper = QHelpEngine(path, self)

        if not self.__helper.setupData() is True:
            dialog = QMessageBox()

            msg = QString(
                self.tr("An error occurred while setting help engine up :\n"))
            msg += (self.__helper.error() + "\n")
            msg += self.tr(
                "It might mean that the format of your help file is not correct.\n"
            )
            msg += self.tr(
                "You can check on-line help at http://wiki.digital-forensic.org"
            )

            dialog.setText(msg)
            dialog.setIcon(QMessageBox.Warning)
            dialog.setWindowTitle(self.tr("Error while loading help"))
            dialog.exec_()
            return

        self.__toc = self.__helper.contentWidget()
        self.__helpBrowser = HelpBrowser(self.__helper)

        # build main widget
        self.__toolbar = QWidget()
        self.__toolbarLayout = QHBoxLayout(self.__toolbar)
        home = QPushButton(QIcon(":home.png"), "")
        previous = QPushButton(QIcon(":previous.png"), "")
        next = QPushButton(QIcon(":next.png"), "")

        # building toolbar
        self.__toolbarLayout.addWidget(home)
        self.__toolbarLayout.addWidget(previous)
        self.__toolbarLayout.addWidget(next)
        self.__toolbarLayout.setContentsMargins(0, 0, 0, 0)
        mainWidgetLayout.addWidget(self.__toolbar)
        mainWidgetLayout.addWidget(self.__helpBrowser)
        self.__mainWidget.insertWidget(0, self.__toc)
        self.__mainWidget.insertWidget(1, self.__uname)
        self.__mainWidget.setStretchFactor(1, 1)
        self.setWidget(self.__mainWidget)

        #connecting `previous`, `home` and `next` buttons
        self.connect(next, SIGNAL("clicked(bool)"),
                     self.__helpBrowser.nextPage)
        self.connect(previous, SIGNAL("clicked(bool)"),
                     self.__helpBrowser.prevPage)
        self.connect(home, SIGNAL("clicked(bool)"), self.__helpBrowser.goHome)
        self.connect(self.__helper.contentWidget(),
                     SIGNAL("linkActivated(const QUrl &)"),
                     self.__helpBrowser.setSource)
Esempio n. 8
0
class __CentralWidget(QWidget):

    ###############################################################################
    # CentralWidget SIGNALS
    ###############################################################################

    """
    splitterCentralRotated()
    """

    ###############################################################################

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.parent = parent
        # This variables are used to save the splitter sizes before hide
        self._splitterMainSizes = None
        self._splitterAreaSizes = None
        self.lateralPanel = None

        hbox = QHBoxLayout(self)
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.setSpacing(0)
        # Create Splitters to divide the UI in: MainPanel, Explorer, Misc
        self._splitterArea = QSplitter(Qt.Horizontal)
        self._splitterMain = QSplitter(Qt.Vertical)

        # Create scrollbar for follow mode
        self.scrollBar = QScrollBar(Qt.Vertical, self)
        self.scrollBar.setFixedWidth(20)
        self.scrollBar.setToolTip("Follow Mode: Scroll the Editors together")
        self.scrollBar.hide()
        self.connect(self.scrollBar, SIGNAL("valueChanged(int)"), self.move_follow_scrolls)

        # Add to Main Layout
        hbox.addWidget(self.scrollBar)
        hbox.addWidget(self._splitterArea)

    def insert_central_container(self, container):
        self.mainContainer = container
        self._splitterMain.insertWidget(0, container)

    def insert_lateral_container(self, container):
        self.lateralPanel = LateralPanel(container)
        self._splitterArea.insertWidget(0, self.lateralPanel)

    def insert_bottom_container(self, container):
        self.misc = container
        self._splitterMain.insertWidget(1, container)

    def showEvent(self, event):
        # Show Event
        QWidget.showEvent(self, event)
        # Avoid recalculate the panel sizes if they are already loaded
        if self._splitterArea.count() == 2:
            return
        # Rearrange widgets on Window
        self._splitterArea.insertWidget(0, self._splitterMain)
        qsettings = QSettings()
        # Lists of sizes as list of QVariant- heightList = [QVariant, QVariant]
        heightList = list(qsettings.value("window/central/mainSize", [(self.height() / 3) * 2, self.height() / 3]))
        widthList = list(qsettings.value("window/central/areaSize", [(self.width() / 6) * 5, self.width() / 6]))
        self._splitterMainSizes = [int(heightList[0]), int(heightList[1])]
        self._splitterAreaSizes = [int(widthList[0]), int(widthList[1])]
        if not event.spontaneous():
            self.change_misc_visibility()
        if bin(settings.UI_LAYOUT)[-1] == "1":
            self.splitter_central_rotate()
        if bin(settings.UI_LAYOUT >> 1)[-1] == "1":
            self.splitter_misc_rotate()
        if bin(settings.UI_LAYOUT >> 2)[-1] == "1":
            self.splitter_central_orientation()
        # Set the sizes to splitters
        self._splitterMain.setSizes(self._splitterMainSizes)
        self._splitterArea.setSizes(self._splitterAreaSizes)

    def change_misc_visibility(self):
        if self.misc.isVisible():
            self._splitterMainSizes = self._splitterMain.sizes()
            self.misc.hide()
            widget = self.mainContainer.get_actual_widget()
            if widget:
                widget.setFocus()
        else:
            self.misc.show()
            self.misc.gain_focus()

    def change_main_visibility(self):
        if self.mainContainer.isVisible():
            self.mainContainer.hide()
        else:
            self.mainContainer.show()

    def change_explorer_visibility(self, force_hide=False):
        if self.lateralPanel.isVisible() or force_hide:
            self._splitterAreaSizes = self._splitterArea.sizes()
            self.lateralPanel.hide()
        else:
            self.lateralPanel.show()

    def splitter_central_rotate(self):
        w1, w2 = self._splitterArea.widget(0), self._splitterArea.widget(1)
        self._splitterArea.insertWidget(0, w2)
        self._splitterArea.insertWidget(1, w1)
        self.emit(SIGNAL("splitterCentralRotated()"))

    def splitter_central_orientation(self):
        if self._splitterArea.orientation() == Qt.Horizontal:
            self._splitterArea.setOrientation(Qt.Vertical)
        else:
            self._splitterArea.setOrientation(Qt.Horizontal)

    def splitter_misc_rotate(self):
        w1, w2 = self._splitterMain.widget(0), self._splitterMain.widget(1)
        self._splitterMain.insertWidget(0, w2)
        self._splitterMain.insertWidget(1, w1)

    def splitter_misc_orientation(self):
        if self._splitterMain.orientation() == Qt.Horizontal:
            self._splitterMain.setOrientation(Qt.Vertical)
        else:
            self._splitterMain.setOrientation(Qt.Horizontal)

    def get_area_sizes(self):
        if self.lateralPanel.isVisible():
            self._splitterAreaSizes = self._splitterArea.sizes()
        return self._splitterAreaSizes

    def get_main_sizes(self):
        if self.misc.isVisible():
            self._splitterMainSizes = self._splitterMain.sizes()
        return self._splitterMainSizes

    def enable_follow_mode_scrollbar(self, val):
        if val:
            editorWidget = self.mainContainer.get_actual_editor()
            maxScroll = editorWidget.verticalScrollBar().maximum()
            position = editorWidget.verticalScrollBar().value()
            self.scrollBar.setMaximum(maxScroll)
            self.scrollBar.setValue(position)
        self.scrollBar.setVisible(val)

    def move_follow_scrolls(self, val):
        widget = self.mainContainer._tabMain.currentWidget()
        diff = widget._sidebarWidget.highest_line - val
        s1 = self.mainContainer._tabMain.currentWidget().verticalScrollBar()
        s2 = self.mainContainer._tabSecondary.currentWidget().verticalScrollBar()
        s1.setValue(val)
        s2.setValue(val + diff)
Esempio n. 9
0
class MainWindow(QWidget, MainWindowGeneric):
    def __init__(self, parent):
        QWidget.__init__(self)
        MainWindowGeneric.__init__(self)
        self._parent = parent
        self.settings = QSettings("NINJA-IDE", "Kunai")

        self.settings.beginGroup("Preferences")
        self.settings.beginGroup("Interface")

        self._vbox = QVBoxLayout(self)
        # Splitters
        self.splitterMain = QSplitter()
        self.splitterCentral = QSplitter(Qt.Vertical)
        # Properties Panel
        self._properties = PropertiesWidget(self)
        # Central
        self._central = CentralWidget(self)
        self.show_start_page()
        self.splitterCentral.insertWidget(self.settings.value("central_tab_position", 0).toInt()[0], self._central)
        # Display Container
        self.container = DisplayContainer(self)
        self._hide_container()
        self.splitterCentral.insertWidget(self.settings.value("container_tab_position", 1).toInt()[0], self.container)
        height = [(self.height() / 3) * 2, self.height() / 3]
        self.splitterCentral.setSizes(
            [
                height[self.settings.value("central_tab_position", 0).toInt()[0]],
                height[self.settings.value("container_tab_position", 1).toInt()[0]],
            ]
        )
        # Size Central Splitter
        self.splitterMain.insertWidget(self.settings.value("main_tab_position", 0).toInt()[0], self.splitterCentral)
        self.splitterMain.insertWidget(self.settings.value("properties_tab_position", 1).toInt()[0], self._properties)
        width = [(self.width() / 6) * 5, self.width() / 6]
        self.splitterMain.setSizes(
            [
                width[self.settings.value("main_tab_position", 0).toInt()[0]],
                width[self.settings.value("properties_tab_position", 1).toInt()[0]],
            ]
        )
        self._vbox.addWidget(self.splitterMain)

        self.settings.endGroup()  # End General Preferences
        self.settings.endGroup()

        # flag for reload_file
        self._reloading = False

        # Shortcuts
        shortCloseTab = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self)
        shortNew = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N), self)
        shortNewProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J), self)
        shortOpen = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_O), self)
        shortOpenProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), self)
        shortSave = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self)
        shortSaveAll = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self)
        shortRedo = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self)
        shortComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_D), self)
        shortHorizontalLine = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_R), self)
        shortIndentLess = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Tab), self)
        shortHideContainer = QShortcut(QKeySequence(Qt.Key_F4), self)
        shortHideEditor = QShortcut(QKeySequence(Qt.Key_F3), self)
        shortHideExplorer = QShortcut(QKeySequence(Qt.Key_F2), self)
        shortRunFile = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F6), self)
        shortRunProgram = QShortcut(QKeySequence(Qt.Key_F6), self)
        shortHideAll = QShortcut(QKeySequence(Qt.Key_F11), self)
        shortFind = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self)
        shortFindReplace = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_H), self)
        shortHelp = QShortcut(QKeySequence(Qt.Key_F1), self)
        shortSplitHorizontal = QShortcut(QKeySequence(Qt.Key_F10), self)
        shortSplitVertical = QShortcut(QKeySequence(Qt.Key_F9), self)
        shortReloadFile = QShortcut(QKeySequence(Qt.Key_F5), self)
        # Signal -> Slot
        self.connect(shortCloseTab, SIGNAL("activated()"), self.close_actual_tab)
        self.connect(shortNew, SIGNAL("activated()"), self.new_editor)
        self.connect(shortNewProject, SIGNAL("activated()"), self.new_project)
        self.connect(shortOpen, SIGNAL("activated()"), self.open_file)
        self.connect(shortOpenProject, SIGNAL("activated()"), self.open_project_folder)
        self.connect(shortSave, SIGNAL("activated()"), self.save)
        self.connect(shortSaveAll, SIGNAL("activated()"), self.save_project)
        self.connect(shortComment, SIGNAL("activated()"), lambda: self._central.obtain_editor().comment())
        self.connect(shortIndentLess, SIGNAL("activated()"), lambda: self._central.obtain_editor().indent_less())
        self.connect(
            shortHorizontalLine, SIGNAL("activated()"), lambda: self._central.obtain_editor().insert_horizontal_line()
        )
        self.connect(shortRedo, SIGNAL("activated()"), lambda: self._central.obtain_editor().redo())
        self.connect(shortHideContainer, SIGNAL("activated()"), self._hide_container)
        self.connect(shortHideEditor, SIGNAL("activated()"), self._hide_editor)
        self.connect(shortHideExplorer, SIGNAL("activated()"), self._hide_explorer)
        self.connect(shortRunFile, SIGNAL("activated()"), self._run_code)
        self.connect(shortRunProgram, SIGNAL("activated()"), self._run_program)
        self.connect(shortHideAll, SIGNAL("activated()"), self._hide_all)
        self.connect(shortFind, SIGNAL("activated()"), self._open_find)
        self.connect(shortFindReplace, SIGNAL("activated()"), self._open_find_replace)
        self.connect(shortHelp, SIGNAL("activated()"), self._show_python_doc)
        self.connect(shortSplitHorizontal, SIGNAL("activated()"), lambda: self.split_tab(True))
        self.connect(shortSplitVertical, SIGNAL("activated()"), lambda: self.split_tab(False))
        self.connect(shortReloadFile, SIGNAL("activated()"), lambda: self.reload_file())

    def change_window_title(self, title):
        self._parent.setWindowTitle("NINJA-IDE - " + title)

    def _open_find(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.focus_find(self._central.obtain_editor())

    def _open_find_replace(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.replace_visibility(True)
        self._parent._status.focus_find(self._central.obtain_editor())

    def _hide_container(self):
        if self.containerIsVisible:
            self.container.hide()
            self.containerIsVisible = False
            self._central.obtain_editor().setFocus()
        else:
            self.container.show()
            self.containerIsVisible = True
            self.container.gain_focus()

    def _hide_editor(self):
        if self._central.isVisible():
            self._central.hide()
        else:
            self._central.show()

    def _hide_explorer(self):
        if self._properties.isVisible():
            self._properties.hide()
        else:
            self._properties.show()

    def _splitter_central_orientation(self):
        if self.splitterCentral.orientation() == Qt.Horizontal:
            self.splitterCentral.setOrientation(Qt.Vertical)
        else:
            self.splitterCentral.setOrientation(Qt.Horizontal)

    def get_splitter_central_orientation(self):
        return self.splitterCentral.orientation()

    def _splitter_main_orientation(self):
        if self.splitterMain.orientation() == Qt.Horizontal:
            self.splitterMain.setOrientation(Qt.Vertical)
        else:
            self.splitterMain.setOrientation(Qt.Horizontal)

    def get_splitter_main_orientation(self):
        return self.splitterMain.orientation()

    def _splitter_main_rotate(self):
        w = self.splitterMain.widget(0)
        w1 = self.splitterMain.widget(1)
        self.splitterMain.insertWidget(0, w1)
        self.splitterMain.insertWidget(1, w)

    def get_splitter_main_position(self):
        w = self.splitterMain.widget(0)
        return w.__class__

    def _splitter_central_rotate(self):
        w = self.splitterCentral.widget(0)
        w1 = self.splitterCentral.widget(1)
        self.splitterCentral.insertWidget(0, w1)
        self.splitterCentral.insertWidget(1, w)

    def get_splitter_central_position(self):
        w = self.splitterCentral.widget(0)
        return w.__class__

    def get_splitter_position_0(self):
        return type(self.splitterCentral.widget(0))

    def get_splitter_main_position_0(self):
        return type(self.splitterMain.widget(0))

    def reload_panels_position(self):
        self.settings = QSettings("NINJA-IDE", "Kunai")

        self.settings.beginGroup("Preferences")
        self.settings.beginGroup("Interface")

        # first with the splitterCentral
        c = self.splitterCentral.widget(0)
        c1 = self.splitterCentral.widget(1)
        if type(c) == CentralWidget:
            self.splitterCentral.insertWidget(self.settings.value("central_tab_position", 0).toInt()[0], c)
            self.splitterCentral.insertWidget(self.settings.value("container_tab_position", 1).toInt()[0], c1)
        else:
            self.splitterCentral.insertWidget(self.settings.value("central_tab_position", 0).toInt()[0], c1)
            self.splitterCentral.insertWidget(self.settings.value("container_tab_position", 1).toInt()[0], c)
        # now with the splitterMain
        m = self.splitterMain.widget(0)
        m1 = self.splitterMain.widget(1)
        if type(m) == QSplitter:
            self.splitterMain.insertWidget(self.settings.value("central_tab_position", 0).toInt()[0], m)
            self.splitterMain.insertWidget(self.settings.value("container_tab_position", 1).toInt()[0], m1)
        else:
            self.splitterMain.insertWidget(self.settings.value("central_tab_position", 0).toInt()[0], m1)
            self.splitterMain.insertWidget(self.settings.value("container_tab_position", 1).toInt()[0], m)

    def get_open_projects(self):
        return self._properties._treeProjects.get_open_projects()

    def _run_code(self):
        if self.save():
            self.container.show()
            self.containerIsVisible = True
            editor = self._central.obtain_editor()
            ext = self.get_file_extension(editor.path)
            if ext == "html":
                height = self.height() / 3
                self.splitterCentral.setSizes([height, height * 2])
                self.container.render_web_page(editor.path)
            elif ext == "py":
                height = self.height() / 3
                self.splitterCentral.setSizes([height * 2, height])
                self.container.run_application(editor.path)
            else:
                self.execute_file(editor.path, ext)

    def _run_program(self, actual=None):
        self.container.show()
        self.containerIsVisible = True
        if actual is None:
            actual = self._properties._treeProjects.actualProject
        if actual is None:
            return
        mainFile = actual.mainFile
        if mainFile == "":
            self._properties._treeProjects.open_project_properties()
            self.containerIsVisible = False
            self.container.hide()
            return
        path = manage_files.create_abs_path(actual.path, mainFile)
        self._central.save_project_files(actual.path)
        lang = actual.lang()
        type_ = actual.projectType
        if lang == "html":
            height = self.height() / 3
            self.splitterCentral.setSizes([height, height * 2])
            self.container.render_web_page(path)
        elif lang == "py":
            height = self.height() / 3
            self.splitterCentral.setSizes([height * 2, height])
            self.container.run_application(path)
        else:
            self.execute_program(path, lang, type_)

    def _stop_program(self):
        self.container.kill_application()

    def _hide_all(self):
        if self._properties.isVisible():
            self._properties.hide()
            self.container.hide()
            self._parent._toolbar.hide()
        else:
            if self.containerIsVisible:
                self.container.show()
            self._properties.show()
            self._parent._toolbar.show()

    def show_start_page(self):
        startPage = Browser(resources.start_page_url)
        self.add_tab(startPage, "Start Page")

    def show_report_bugs(self):
        bugsPage = Browser(resources.bugs_page)
        self.add_tab(bugsPage, "Report Bugs!")

    def _show_python_doc(self):
        process = runner.start_pydoc()
        docPage = Browser(process[1], process[0])
        self.add_tab(docPage, "Python Documentation")

    def new_editor(self, lang="py"):
        if not self._reloading:
            editor = factory_editor(lang, self._central.actual_tab())
            self.add_tab(editor, "New Document")

    def add_tab(self, component, title):
        self._central.actual_tab().add_tab(component, title)

    def split_tab(self, option):
        if option:
            self._central.show_split(Qt.Horizontal)
        else:
            self._central.show_split(Qt.Vertical)

    def new_project(self):
        project = WizardNewProject(self)
        project.show()

    def show_preferences(self):
        prefs = PreferencesWindow(self)
        prefs.show()

    def open_document(self, fileName, project=None):
        try:
            if not self._central.actual_tab().is_open(fileName):
                self._central.actual_tab().notOpening = False
                editor = factory_editor(fileName, self._central.actual_tab(), project)
                content = self.read_file_content(fileName)
                editor.setPlainText(content)
                editor.path = fileName
                editor.ask_if_externally_modified = True
                # self.add_tab(editor, self.get_file_name(fileName))
                if not editor.has_write_permission():
                    fileName += " (Read-Only)"
                self.add_tab(editor, self.get_file_name(fileName))
                self.change_window_title(fileName)
            else:
                self._central.actual_tab().move_to_open(fileName)
        except Exception, reason:
            print reason
            QMessageBox.information(self, "Incorrect File", "The file couldn't be open")
        self._central.actual_tab().notOpening = True
Esempio n. 10
0
class MainWindow(QWidget, MainWindowGeneric):
    def __init__(self, parent):
        QWidget.__init__(self)
        MainWindowGeneric.__init__(self)
        self._parent = parent
        self.settings = QSettings('NINJA-IDE', 'Kunai')

        self.settings.beginGroup('Preferences')
        self.settings.beginGroup('Interface')

        self._vbox = QVBoxLayout(self)
        #Splitters
        self.splitterMain = QSplitter()
        self.splitterCentral = QSplitter(Qt.Vertical)
        #Properties Panel
        self._properties = PropertiesWidget(self)
        #Central
        self._central = CentralWidget(self)
        self.show_start_page()
        self.splitterCentral.insertWidget(
            self.settings.value('central_tab_position', 0).toInt()[0],
            self._central)
        #Display Container
        self.container = DisplayContainer(self)
        self._hide_container()
        self.splitterCentral.insertWidget(
            self.settings.value('container_tab_position', 1).toInt()[0],
            self.container)
        height = [(self.height() / 3) * 2, self.height() / 3]
        self.splitterCentral.setSizes([height[self.settings.value('central_tab_position', 0).toInt()[0]], height[self\
        .settings.value('container_tab_position', 1).toInt()[0]]])
        #Size Central Splitter
        self.splitterMain.insertWidget(
            self.settings.value('main_tab_position', 0).toInt()[0],
            self.splitterCentral)
        self.splitterMain.insertWidget(
            self.settings.value('properties_tab_position', 1).toInt()[0],
            self._properties)
        width = [(self.width() / 6) * 5, self.width() / 6]
        self.splitterMain.setSizes([width[self.settings.value('main_tab_position', 0).toInt()[0]],\
         width[self.settings.value('properties_tab_position', 1).toInt()[0]]])
        self._vbox.addWidget(self.splitterMain)

        self.settings.endGroup()  #End General Preferences
        self.settings.endGroup()

        #flag for reload_file
        self._reloading = False

        #Shortcuts
        shortCloseTab = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self)
        shortNew = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N), self)
        shortNewProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J), self)
        shortOpen = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_O), self)
        shortOpenProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), self)
        shortSave = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self)
        shortSaveAll = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S),
                                 self)
        shortRedo = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self)
        shortComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_D), self)
        shortHorizontalLine = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_R), self)
        shortIndentLess = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Tab), self)
        shortHideContainer = QShortcut(QKeySequence(Qt.Key_F4), self)
        shortHideEditor = QShortcut(QKeySequence(Qt.Key_F3), self)
        shortHideExplorer = QShortcut(QKeySequence(Qt.Key_F2), self)
        shortRunFile = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F6), self)
        shortRunProgram = QShortcut(QKeySequence(Qt.Key_F6), self)
        shortHideAll = QShortcut(QKeySequence(Qt.Key_F11), self)
        shortFind = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self)
        shortFindReplace = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_H), self)
        shortHelp = QShortcut(QKeySequence(Qt.Key_F1), self)
        shortSplitHorizontal = QShortcut(QKeySequence(Qt.Key_F10), self)
        shortSplitVertical = QShortcut(QKeySequence(Qt.Key_F9), self)
        shortReloadFile = QShortcut(QKeySequence(Qt.Key_F5), self)
        #Signal -> Slot
        self.connect(shortCloseTab, SIGNAL("activated()"),
                     self.close_actual_tab)
        self.connect(shortNew, SIGNAL("activated()"), self.new_editor)
        self.connect(shortNewProject, SIGNAL("activated()"), self.new_project)
        self.connect(shortOpen, SIGNAL("activated()"), self.open_file)
        self.connect(shortOpenProject, SIGNAL("activated()"),
                     self.open_project_folder)
        self.connect(shortSave, SIGNAL("activated()"), self.save)
        self.connect(shortSaveAll, SIGNAL("activated()"), self.save_project)
        self.connect(shortComment, SIGNAL("activated()"),
                     lambda: self._central.obtain_editor().comment())
        self.connect(shortIndentLess, SIGNAL("activated()"),
                     lambda: self._central.obtain_editor().indent_less())
        self.connect(
            shortHorizontalLine, SIGNAL("activated()"),
            lambda: self._central.obtain_editor().insert_horizontal_line())
        self.connect(shortRedo, SIGNAL("activated()"),
                     lambda: self._central.obtain_editor().redo())
        self.connect(shortHideContainer, SIGNAL("activated()"),
                     self._hide_container)
        self.connect(shortHideEditor, SIGNAL("activated()"), self._hide_editor)
        self.connect(shortHideExplorer, SIGNAL("activated()"),
                     self._hide_explorer)
        self.connect(shortRunFile, SIGNAL("activated()"), self._run_code)
        self.connect(shortRunProgram, SIGNAL("activated()"), self._run_program)
        self.connect(shortHideAll, SIGNAL("activated()"), self._hide_all)
        self.connect(shortFind, SIGNAL("activated()"), self._open_find)
        self.connect(shortFindReplace, SIGNAL("activated()"),
                     self._open_find_replace)
        self.connect(shortHelp, SIGNAL("activated()"), self._show_python_doc)
        self.connect(shortSplitHorizontal, SIGNAL("activated()"),
                     lambda: self.split_tab(True))
        self.connect(shortSplitVertical, SIGNAL("activated()"),
                     lambda: self.split_tab(False))
        self.connect(shortReloadFile, SIGNAL("activated()"),
                     lambda: self.reload_file())

    def change_window_title(self, title):
        self._parent.setWindowTitle('NINJA-IDE - ' + title)

    def _open_find(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.focus_find(self._central.obtain_editor())

    def _open_find_replace(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.replace_visibility(True)
        self._parent._status.focus_find(self._central.obtain_editor())

    def _hide_container(self):
        if self.containerIsVisible:
            self.container.hide()
            self.containerIsVisible = False
            self._central.obtain_editor().setFocus()
        else:
            self.container.show()
            self.containerIsVisible = True
            self.container.gain_focus()

    def _hide_editor(self):
        if self._central.isVisible():
            self._central.hide()
        else:
            self._central.show()

    def _hide_explorer(self):
        if self._properties.isVisible():
            self._properties.hide()
        else:
            self._properties.show()

    def _splitter_central_orientation(self):
        if self.splitterCentral.orientation() == Qt.Horizontal:
            self.splitterCentral.setOrientation(Qt.Vertical)
        else:
            self.splitterCentral.setOrientation(Qt.Horizontal)

    def get_splitter_central_orientation(self):
        return self.splitterCentral.orientation()

    def _splitter_main_orientation(self):
        if self.splitterMain.orientation() == Qt.Horizontal:
            self.splitterMain.setOrientation(Qt.Vertical)
        else:
            self.splitterMain.setOrientation(Qt.Horizontal)

    def get_splitter_main_orientation(self):
        return self.splitterMain.orientation()

    def _splitter_main_rotate(self):
        w = self.splitterMain.widget(0)
        w1 = self.splitterMain.widget(1)
        self.splitterMain.insertWidget(0, w1)
        self.splitterMain.insertWidget(1, w)

    def get_splitter_main_position(self):
        w = self.splitterMain.widget(0)
        return w.__class__

    def _splitter_central_rotate(self):
        w = self.splitterCentral.widget(0)
        w1 = self.splitterCentral.widget(1)
        self.splitterCentral.insertWidget(0, w1)
        self.splitterCentral.insertWidget(1, w)

    def get_splitter_central_position(self):
        w = self.splitterCentral.widget(0)
        return w.__class__

    def get_splitter_position_0(self):
        return type(self.splitterCentral.widget(0))

    def get_splitter_main_position_0(self):
        return type(self.splitterMain.widget(0))

    def reload_panels_position(self):
        self.settings = QSettings('NINJA-IDE', 'Kunai')

        self.settings.beginGroup('Preferences')
        self.settings.beginGroup('Interface')

        #first with the splitterCentral
        c = self.splitterCentral.widget(0)
        c1 = self.splitterCentral.widget(1)
        if (type(c) == CentralWidget):
            self.splitterCentral.insertWidget(
                self.settings.value('central_tab_position', 0).toInt()[0], c)
            self.splitterCentral.insertWidget(
                self.settings.value('container_tab_position', 1).toInt()[0],
                c1)
        else:
            self.splitterCentral.insertWidget(
                self.settings.value('central_tab_position', 0).toInt()[0], c1)
            self.splitterCentral.insertWidget(
                self.settings.value('container_tab_position', 1).toInt()[0], c)
        #now with the splitterMain
        m = self.splitterMain.widget(0)
        m1 = self.splitterMain.widget(1)
        if (type(m) == QSplitter):
            self.splitterMain.insertWidget(
                self.settings.value('central_tab_position', 0).toInt()[0], m)
            self.splitterMain.insertWidget(
                self.settings.value('container_tab_position', 1).toInt()[0],
                m1)
        else:
            self.splitterMain.insertWidget(
                self.settings.value('central_tab_position', 0).toInt()[0], m1)
            self.splitterMain.insertWidget(
                self.settings.value('container_tab_position', 1).toInt()[0], m)

    def get_open_projects(self):
        return self._properties._treeProjects.get_open_projects()

    def _run_code(self):
        if self.save():
            self.container.show()
            self.containerIsVisible = True
            editor = self._central.obtain_editor()
            ext = self.get_file_extension(editor.path)
            if ext == 'html':
                height = self.height() / 3
                self.splitterCentral.setSizes([height, height * 2])
                self.container.render_web_page(editor.path)
            elif ext == 'py':
                height = self.height() / 3
                self.splitterCentral.setSizes([height * 2, height])
                self.container.run_application(editor.path)
            else:
                self.execute_file(editor.path, ext)

    def _run_program(self, actual=None):
        self.container.show()
        self.containerIsVisible = True
        if actual is None:
            actual = self._properties._treeProjects.actualProject
        if actual is None:
            return
        mainFile = actual.mainFile
        if mainFile == '':
            self._properties._treeProjects.open_project_properties()
            self.containerIsVisible = False
            self.container.hide()
            return
        path = manage_files.create_abs_path(actual.path, mainFile)
        self._central.save_project_files(actual.path)
        lang = actual.lang()
        type_ = actual.projectType
        if lang == 'html':
            height = self.height() / 3
            self.splitterCentral.setSizes([height, height * 2])
            self.container.render_web_page(path)
        elif lang == 'py':
            height = self.height() / 3
            self.splitterCentral.setSizes([height * 2, height])
            self.container.run_application(path)
        else:
            self.execute_program(path, lang, type_)

    def _stop_program(self):
        self.container.kill_application()

    def _hide_all(self):
        if self._properties.isVisible():
            self._properties.hide()
            self.container.hide()
            self._parent._toolbar.hide()
        else:
            if self.containerIsVisible:
                self.container.show()
            self._properties.show()
            self._parent._toolbar.show()

    def show_start_page(self):
        startPage = Browser(resources.start_page_url)
        self.add_tab(startPage, 'Start Page')

    def show_report_bugs(self):
        bugsPage = Browser(resources.bugs_page)
        self.add_tab(bugsPage, 'Report Bugs!')

    def _show_python_doc(self):
        process = runner.start_pydoc()
        docPage = Browser(process[1], process[0])
        self.add_tab(docPage, 'Python Documentation')

    def new_editor(self, lang='py'):
        if not self._reloading:
            editor = factory_editor(lang, self._central.actual_tab())
            self.add_tab(editor, 'New Document')

    def add_tab(self, component, title):
        self._central.actual_tab().add_tab(component, title)

    def split_tab(self, option):
        if option:
            self._central.show_split(Qt.Horizontal)
        else:
            self._central.show_split(Qt.Vertical)

    def new_project(self):
        project = WizardNewProject(self)
        project.show()

    def show_preferences(self):
        prefs = PreferencesWindow(self)
        prefs.show()

    def open_document(self, fileName, project=None):
        try:
            if not self._central.actual_tab().is_open(fileName):
                self._central.actual_tab().notOpening = False
                editor = factory_editor(fileName, self._central.actual_tab(),
                                        project)
                content = self.read_file_content(fileName)
                editor.setPlainText(content)
                editor.path = fileName
                editor.ask_if_externally_modified = True
                #self.add_tab(editor, self.get_file_name(fileName))
                if not editor.has_write_permission():
                    fileName += ' (Read-Only)'
                self.add_tab(editor, self.get_file_name(fileName))
                self.change_window_title(fileName)
            else:
                self._central.actual_tab().move_to_open(fileName)
        except Exception, reason:
            print reason
            QMessageBox.information(self, 'Incorrect File',
                                    'The file couldn\'t be open')
        self._central.actual_tab().notOpening = True
Esempio n. 11
0
class MainWindow(QWidget, MainWindowGeneric):

    def __init__(self, parent):
        QWidget.__init__(self)
        MainWindowGeneric.__init__(self)
        self._parent = parent

        self._vbox = QVBoxLayout(self)
        #Splitters
        self.splitterMain = QSplitter()
        self.splitterCentral = QSplitter(Qt.Vertical)
        #Properties Panel
        self._properties = PropertiesWidget(self)
        #Central
        self._central = CentralWidget(self)
        self.show_start_page()
        self.splitterCentral.addWidget(self._central)
        #Display Container
        self.container = DisplayContainer(self)
        self._hide_container()
        self.splitterCentral.addWidget(self.container)
        height = [(self.height() / 3) * 2, self.height() / 3]
        self.splitterCentral.setSizes([height[0], height[1]])
        #Size Central Splitter
        self.splitterMain.addWidget(self.splitterCentral)
        self.splitterMain.addWidget(self._properties)
        width = [(self.width() / 6) * 5, self.width() / 6]
        self.splitterMain.setSizes([width[0], width[1]])
        self._vbox.addWidget(self.splitterMain)

        #flag for reload_file
        self._reloading = False

        #Shortcuts
        shortCloseTab = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self)
        shortNew = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N), self)
        shortNewProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J), self)
        shortOpen = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_O), self)
        shortOpenProject = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), self)
        shortSave = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self)
        shortSaveAll = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self)
        shortPrint = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_I), self)
        shortRedo = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self)
        shortComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_D), self)
        shortHorizontalLine = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_R), self)
        shortTitleComment = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T), self)
        shortIndentLess = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Tab), self)
        shortHideContainer = QShortcut(QKeySequence(Qt.Key_F4), self)
        shortHideEditor = QShortcut(QKeySequence(Qt.Key_F3), self)
        shortHideExplorer = QShortcut(QKeySequence(Qt.Key_F2), self)
        shortRunFile = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F6), self)
        shortRunProgram = QShortcut(QKeySequence(Qt.Key_F6), self)
        shortHideAll = QShortcut(QKeySequence(Qt.Key_F11), self)
        shortFind = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self)
        shortFindReplace = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_H), self)
        shortHelp = QShortcut(QKeySequence(Qt.Key_F1), self)
        shortSplitHorizontal = QShortcut(QKeySequence(Qt.Key_F10), self)
        shortSplitVertical = QShortcut(QKeySequence(Qt.Key_F9), self)
        shortFollowMode = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F10), self)
        shortReloadFile = QShortcut(QKeySequence(Qt.Key_F5), self)
        shortShowProjectsTree = QShortcut(QKeySequence(Qt.ALT + Qt.Key_1), self)
        shortShowSymbolsTree = QShortcut(QKeySequence(Qt.ALT + Qt.Key_2), self)
        #Signal -> Slot
        self.connect(shortCloseTab, SIGNAL("activated()"), self.close_actual_tab)
        self.connect(shortNew, SIGNAL("activated()"), self.new_editor)
        self.connect(shortNewProject, SIGNAL("activated()"), self.new_project)
        self.connect(shortOpen, SIGNAL("activated()"), self.open_file)
        self.connect(shortOpenProject, SIGNAL("activated()"), self.open_project_folder)
        self.connect(shortSave, SIGNAL("activated()"), self.save)
        self.connect(shortSaveAll, SIGNAL("activated()"), self.save_project)
        self.connect(shortPrint, SIGNAL("activated()"), self._print_file)
        self.connect(shortComment, SIGNAL("activated()"), lambda: self._central.obtain_editor().comment())
        self.connect(shortIndentLess, SIGNAL("activated()"), lambda: self._central.obtain_editor().indent_less())
        self.connect(shortHorizontalLine, SIGNAL("activated()"), lambda: self._central.obtain_editor().insert_horizontal_line())
        self.connect(shortTitleComment, SIGNAL("activated()"), lambda: self._central.obtain_editor().insert_title_comment())
        self.connect(shortRedo, SIGNAL("activated()"), lambda: self._central.obtain_editor().redo())
        self.connect(shortHideContainer, SIGNAL("activated()"), self._hide_container)
        self.connect(shortHideEditor, SIGNAL("activated()"), self._hide_editor)
        self.connect(shortHideExplorer, SIGNAL("activated()"), self._hide_explorer)
        self.connect(shortRunFile, SIGNAL("activated()"), self._run_code)
        self.connect(shortRunProgram, SIGNAL("activated()"), self._run_program)
        self.connect(shortHideAll, SIGNAL("activated()"), self._hide_all)
        self.connect(shortFind, SIGNAL("activated()"), self._open_find)
        self.connect(shortFindReplace, SIGNAL("activated()"), self._open_find_replace)
        self.connect(shortHelp, SIGNAL("activated()"), self._show_python_doc)
        self.connect(shortSplitHorizontal, SIGNAL("activated()"), lambda: self.split_tab(True))
        self.connect(shortSplitVertical, SIGNAL("activated()"), lambda: self.split_tab(False))
        self.connect(shortFollowMode, SIGNAL("activated()"), self._view_follow_mode)
        self.connect(shortReloadFile, SIGNAL("activated()"), lambda: self.reload_file())
        self.connect(shortShowProjectsTree, SIGNAL("activated()"), self.show_projects_tree)
        self.connect(shortShowSymbolsTree, SIGNAL("activated()"), self.show_symbols_tree)

    def change_window_title(self, title):
        self._parent.setWindowTitle('NINJA-IDE - ' + title)

    def _open_find(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.focus_find(self._central.obtain_editor())

    def _open_find_replace(self):
        if not self._parent._status.isVisible():
            self._parent._status.show()
        self._parent._status.replace_visibility(True)
        self._parent._status.focus_find(self._central.obtain_editor())

    def _print_file(self):
        self.printer = QPrinter(QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.A4)
        if self._central.obtain_editor().path:
            fileName = manage_files.get_basename(self._central.obtain_editor().path)
            fileName = fileName[:fileName.rfind('.')] + '.pdf'
        else:
            fileName = 'newDocument.pdf'
        self.printer.setOutputFileName(fileName)
        dialog = QPrintDialog(self.printer, self)
        if dialog.exec_():
            self.printer.setDocName(manage_files.get_basename(self._central.obtain_editor().path))
            self._central.obtain_editor().document().print_(self.printer)

    def _hide_container(self):
        if self.containerIsVisible:
            self.container.hide()
            self.containerIsVisible = False
            self._central.obtain_editor().setFocus()
        else:
            self.container.show()
            self.containerIsVisible = True
            self.container.gain_focus()

    def _hide_editor(self):
        if self._central.isVisible():
            self._central.hide()
        else:
            self._central.show()

    def _hide_explorer(self):
        if self._properties.isVisible():
            self._properties.hide()
        else:
            self._properties.show()

    def _splitter_central_orientation(self):
        if self.splitterCentral.orientation() == Qt.Horizontal:
            self.splitterCentral.setOrientation(Qt.Vertical)
        else:
            self.splitterCentral.setOrientation(Qt.Horizontal)

    def get_splitter_central_orientation(self):
        return self.splitterCentral.orientation()

    def _splitter_main_orientation(self):
        if self.splitterMain.orientation() == Qt.Horizontal:
            self.splitterMain.setOrientation(Qt.Vertical)
        else:
            self.splitterMain.setOrientation(Qt.Horizontal)

    def get_splitter_main_orientation(self):
        return self.splitterMain.orientation()

    def _splitter_main_rotate(self):
        w = self.splitterMain.widget(0)
        w1 = self.splitterMain.widget(1)
        if type(w) is PropertiesWidget:
            w.setTabPosition(QTabWidget.East)
        else:
            w1.setTabPosition(QTabWidget.West)
        self.splitterMain.insertWidget(0, w1)
        self.splitterMain.insertWidget(1, w)

    def get_splitter_main_position(self):
        w = self.splitterMain.widget(0)
        return w.__class__

    def _splitter_central_rotate(self):
        w = self.splitterCentral.widget(0)
        w1 = self.splitterCentral.widget(1)
        self.splitterCentral.insertWidget(0, w1)
        self.splitterCentral.insertWidget(1, w)

    def get_splitter_central_position(self):
        w = self.splitterCentral.widget(0)
        return w.__class__

    def get_splitter_position_0(self):
        return type(self.splitterCentral.widget(0))

    def get_splitter_main_position_0(self):
        return type(self.splitterMain.widget(0))

    def reload_panels_position(self):
        self.settings = QSettings('NINJA-IDE', 'Kunai')

        self.settings.beginGroup('Preferences')
        self.settings.beginGroup('Interface')

        #first with the splitterCentral
        c = self.splitterCentral.widget(0)
        c1 = self.splitterCentral.widget(1)
        if (type(c) == CentralWidget):
            self.splitterCentral.insertWidget(self.settings.value('central_tab_position', 0).toInt()[0], c)
            self.splitterCentral.insertWidget(self.settings.value('container_tab_position', 1).toInt()[0], c1)
        else:
            self.splitterCentral.insertWidget(self.settings.value('central_tab_position', 0).toInt()[0], c1)
            self.splitterCentral.insertWidget(self.settings.value('container_tab_position', 1).toInt()[0], c)
        #now with the splitterMain
        m = self.splitterMain.widget(0)
        m1 = self.splitterMain.widget(1)
        if (type(m) == QSplitter):
            self.splitterMain.insertWidget(self.settings.value('central_tab_position', 0).toInt()[0], m)
            self.splitterMain.insertWidget(self.settings.value('container_tab_position', 1).toInt()[0], m1)
        else:
            self.splitterMain.insertWidget(self.settings.value('central_tab_position', 0).toInt()[0], m1)
            self.splitterMain.insertWidget(self.settings.value('container_tab_position', 1).toInt()[0], m)

    def get_open_projects(self):
        return self._properties._treeProjects.get_open_projects()

    def _run_code(self):
        if self.save():
            self.container.show()
            self.containerIsVisible = True
            editor = self._central.obtain_editor()
            ext = self.get_file_extension(editor.path)
            if ext == 'html':
                height = self.height() / 3
                self.splitterCentral.setSizes([height, height * 2])
                self.container.render_web_page(editor.path)
            elif ext == 'py':
                height = self.height() / 3
                self.splitterCentral.setSizes([height * 2, height])
                self.container.run_application(editor.path)
            else:
                self.execute_file(editor.path, ext)

    def _run_program(self, actual=None):
        self.container.show()
        self.containerIsVisible = True
        if actual is None:
            actual = self._properties._treeProjects.actualProject
        if actual is None:
            return
        mainFile = actual.mainFile
        if mainFile == '':
            self._properties._treeProjects.open_project_properties()
            self.containerIsVisible = False
            self.container.hide()
            return
        path = manage_files.create_abs_path(actual.path, mainFile)
        self._central.save_project_files(actual.path)
        lang = actual.lang()
        type_ = actual.projectType
        if lang == 'html':
            height = self.height() / 3
            self.splitterCentral.setSizes([height, height * 2])
            self.container.render_web_page(path)
        elif lang == 'py':
            height = self.height() / 3
            self.splitterCentral.setSizes([height * 2, height])
            self.container.run_application(path, actual.pythonPath)
        else:
            self.execute_program(path, lang, type_)

    def _stop_program(self):
        self.container.kill_application()

    def _hide_all(self):
        if self._properties.isVisible():
            self._properties.hide()
            self.container.hide()
            self._parent._toolbar.hide()
        else:
            if self.containerIsVisible:
                self.container.show()
            self._properties.show()
            self._parent._toolbar.show()

    def show_start_page(self):
        startPage = Browser(resources.start_page_url, None, self)
        self.add_tab(startPage, 'Start Page')

    def show_report_bugs(self):
        bugsPage = Browser(resources.bugs_page)
        self.add_tab(bugsPage, 'Report Bugs!')

    def show_plugins_doc(self):
        bugsPage = Browser(resources.plugins_doc)
        self.add_tab(bugsPage, 'How to Write NINJA-IDE plugins')

    def _show_python_doc(self):
        process = runner.start_pydoc()
        docPage = Browser(process[1], process[0])
        self.add_tab(docPage, 'Python Documentation')

    def new_editor(self, lang='py'):
        if not self._reloading:
            editor = factory_editor(lang, self._central.actual_tab())
            self.add_tab(editor, 'New Document')

    def add_tab(self, component, title):
        self._central.actual_tab().add_tab(component, title)

    def split_tab(self, option):
        if option:
            self._central.show_split(Qt.Horizontal)
        else:
            self._central.show_split(Qt.Vertical)

    def _view_follow_mode(self):
        self._central._show_follow_mode()

    def new_project(self):
        project = WizardNewProject(self)
        project.show()

    def show_preferences(self):
        prefs = PreferencesWindow(self)
        prefs.show()

    def open_document(self, fileName, project=None):
        try:
            if not self._central.actual_tab().is_open(fileName):
                self._central.actual_tab().notOpening = False
                editor = factory_editor(fileName, self._central.actual_tab(), project)
                content = self.read_file_content(fileName)
                editor.setPlainText(content)
                editor.path = fileName
                editor.ask_if_externally_modified = True
                #self.add_tab(editor, self.get_file_name(fileName))
                if not editor.has_write_permission():
                    fileName += ' (Read-Only)'
                self.add_tab(editor, self.get_file_name(fileName))
                self.change_window_title(fileName)
                editor.find_errors_and_check_style()
            else:
                self._central.actual_tab().move_to_open(fileName)
        except Exception, reason:
            print reason
            QMessageBox.information(self, 'Incorrect File', 'The file couldn\'t be open')
        self._central.actual_tab().notOpening = True