Beispiel #1
0
    def popup_menu(self, position):

        selected_row = self.view.rowAt(position.y())

        if selected_row >= 0 and self._used_categories and len(
                self._used_categories) > 1:
            category_menu = QMenu(_("Categories"))
            selected_doc = self.model.object_at(selected_row)

            category_actions = []
            for category in self._used_categories:
                a = QAction(category.full_name, category_menu)
                a.setData(category)

                a.setEnabled(selected_doc.document_category_id !=
                             category.document_category_id)

                category_menu.addAction(a)
                category_actions.append(a)

            action = category_menu.exec_(QCursor.pos())

            if action:
                new_category = action.data()

                if selected_doc.document_category_id != new_category.document_category_id:
                    selected_doc.document_category_id = new_category.document_category_id
                    self.model.signal_object_change(selected_doc)
    def on_show_supported_type(self):
        node_types = sorted(
            [n_type for (n_type, nice, attr) in
             MTTSettings.SUPPORTED_TYPE] + MTTSettings.UNSUPPORTED_TYPE)
        support_info = self.sender()
        support_info.clear()

        for node_type in node_types:
            current = QAction(node_type, self)
            current.setEnabled(False)
            current.setCheckable(True)
            current.setChecked(node_type not in MTTSettings.UNSUPPORTED_TYPE)
            support_info.addAction(current)
    def on_show_supported_type(self):
        node_types = sorted(
            [n_type for (n_type, nice, attr) in MTTSettings.SUPPORTED_TYPE] +
            MTTSettings.UNSUPPORTED_TYPE)
        support_info = self.sender()
        support_info.clear()

        for node_type in node_types:
            current = QAction(node_type, self)
            current.setEnabled(False)
            current.setCheckable(True)
            current.setChecked(node_type not in MTTSettings.UNSUPPORTED_TYPE)
            support_info.addAction(current)
Beispiel #4
0
class ChatWindow(QMainWindow):
    """
    The chat application window.
    """
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.chat_widget = ChatWidget(self)
        self.setCentralWidget(self.chat_widget)
        # set up all actions
        self.chat_widget.message.connect(self.statusBar().showMessage)
        app_menu = self.menuBar().addMenu('&Application')
        self.connect_action = QAction('&Connect', self)
        self.connect_action.triggered.connect(self._connect)
        self.connect_action.setShortcut('Ctrl+C')
        app_menu.addAction(self.connect_action)
        app_menu.addSeparator()
        self.quit_server_action = QAction('Quit &server', self)
        self.quit_server_action.triggered.connect(self._quit_server)
        self.quit_server_action.setEnabled(False)
        self.quit_server_action.setShortcut('Ctrl+D')
        app_menu.addAction(self.quit_server_action)
        quit_action = QAction(
            self.style().standardIcon(QStyle.SP_DialogCloseButton), '&Quit',
            self)
        quit_action.triggered.connect(QApplication.instance().quit)
        quit_action.setShortcut('Ctrl+Q')
        app_menu.addAction(quit_action)
        # attempt to connect
        self._connect()

    def _quit_server(self):
        if self.chat_widget.connected:
            self.chat_widget.send_text('quit')

    def _connect(self):
        # connect to a server
        if not self.chat_widget.connected:
            self.chat_widget.connection = QTcpSocket()
            # upon connection, disable the connect action, and enable the
            # quit server action
            self.chat_widget.connection.connected.connect(
                partial(self.quit_server_action.setEnabled, True))
            self.chat_widget.connection.connected.connect(
                partial(self.connect_action.setDisabled, True))
            # to the reverse thing upon disconnection
            self.chat_widget.connection.disconnected.connect(
                partial(self.connect_action.setEnabled, True))
            self.chat_widget.connection.disconnected.connect(
                partial(self.quit_server_action.setDisabled, True))
            # connect to the chat server
            self.chat_widget.connection.connectToHost(HOST_ADDRESS, PORT)
class ChatWindow(QMainWindow):
    """
    The chat application window.
    """
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.chat_widget = ChatWidget(self)
        self.setCentralWidget(self.chat_widget)
        # set up all actions
        self.chat_widget.message.connect(self.statusBar().showMessage)
        app_menu = self.menuBar().addMenu('&Application')
        self.connect_action = QAction('&Connect', self)
        self.connect_action.triggered.connect(self._connect)
        self.connect_action.setShortcut('Ctrl+C')
        app_menu.addAction(self.connect_action)
        app_menu.addSeparator()
        self.quit_server_action = QAction('Quit &server', self)
        self.quit_server_action.triggered.connect(self._quit_server)
        self.quit_server_action.setEnabled(False)
        self.quit_server_action.setShortcut('Ctrl+D')
        app_menu.addAction(self.quit_server_action)
        quit_action = QAction(self.style().standardIcon(
            QStyle.SP_DialogCloseButton), '&Quit', self)
        quit_action.triggered.connect(QApplication.instance().quit)
        quit_action.setShortcut('Ctrl+Q')
        app_menu.addAction(quit_action)
        # attempt to connect
        self._connect()

    def _quit_server(self):
        if self.chat_widget.connected:
            self.chat_widget.send_text('quit')

    def _connect(self):
        # connect to a server
        if not self.chat_widget.connected:
            self.chat_widget.connection = QTcpSocket()
            # upon connection, disable the connect action, and enable the
            # quit server action
            self.chat_widget.connection.connected.connect(
                partial(self.quit_server_action.setEnabled, True))
            self.chat_widget.connection.connected.connect(
                partial(self.connect_action.setDisabled, True))
            # to the reverse thing upon disconnection
            self.chat_widget.connection.disconnected.connect(
                partial(self.connect_action.setEnabled, True))
            self.chat_widget.connection.disconnected.connect(
                partial(self.quit_server_action.setDisabled, True))
            # connect to the chat server
            self.chat_widget.connection.connectToHost(HOST_ADDRESS, PORT)
Beispiel #6
0
def populate_menu( menu, action_target, list_actions, context=Qt.WindowShortcut):
    """ action_target is a QWidget where the menu's action can be
    added so that they are callable from there
    """

    global configuration
    global user_session

    for t in list_actions:
        # t = (Text, Slot to call, KeySequence shortcut, roles which can use the action)
        # t = (QAction, roles which can use the action)
        # if QAction then slot, KeySequence will be ignored

        roles = a = None
        if isinstance( t[0], QAction):
            a = t[0]
            roles = t[1]
            if a.parent() is None:
                action_target.addAction(a)
        elif isinstance( t[0], QMenu):
            a = t[0]
            roles = t[1]
        else:
            a = QAction(t[0],action_target) # text, parent

            if t[1]:
                a.triggered.connect(t[1])

            if t[2]:
                a.setShortcut(t[2])
                a.setShortcutContext(context)
            roles = t[3]
            action_target.addAction(a)

        if roles is not None:
            a.setEnabled(user_session.has_any_roles(roles))

        if isinstance( a, QMenu):
            menu.addMenu(a)
        else:
            menu.addAction(a)
Beispiel #7
0
def createAction(self, icon, toolTip, statusTip, scripted=False):
    """
    TOWRITE

    :param `icon`: TOWRITE
    :type `icon`: QString
    :param `toolTip`: TOWRITE
    :type `toolTip`: QString
    :param `statusTip`: TOWRITE
    :type `statusTip`: QString
    :param `scripted`: TOWRITE
    :type `scripted`: bool
    :rtype: `QAction`_

    .. TODO:: send the global Icon, Image, Commands Dirs in to be used.

    """
    connect = self.connect  # NOT local optimization, but for ease of the code looking similar to the C++ whash
    mdiArea = self.mdiArea  # ditto

    ACTION = QAction(
        QIcon(self.gIconDir + os.sep + self.getSettingsGeneralIconTheme() +
              "/" + icon + ".png"), toolTip, self
    )  # QAction *  # TODO: Qt4.7 wont load icons without an extension...
    ACTION.setStatusTip(statusTip)
    ACTION.setObjectName(icon)
    # TODO: Set What's This Context Help to statusTip for now so there is some infos there.
    # Make custom whats this context help popup with more descriptive help than just
    # the status bar/tip one liner(short but not real long) with a hyperlink in the custom popup
    # at the bottom to open full help file description. Ex: like wxPython AGW's SuperToolTip.
    ACTION.setWhatsThis(statusTip)
    # TODO: Finish All Commands ... <.<

    if icon == "donothing":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("doNothing()"))
    elif icon == "new":
        ACTION.setShortcut(QKeySequence.New)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("newFile()"))
    elif icon == "open":
        ACTION.setShortcut(QKeySequence.Open)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("openFile()"))
    elif icon == "save":
        ACTION.setShortcut(QKeySequence.Save)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("savefile()"))
    elif icon == "saveas":
        ACTION.setShortcut(QKeySequence.SaveAs)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("saveasfile()"))
    elif icon == "print":
        ACTION.setShortcut(QKeySequence.Print)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("print_()"))
    elif icon == "designdetails":
        ACTION.setShortcut(QKeySequence("Ctrl+D"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("designDetails()"))
    elif icon == "exit":
        ACTION.setShortcut(QKeySequence("Ctrl+Q"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("exit()"))

    elif icon == "cut":
        ACTION.setShortcut(QKeySequence.Cut)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("cut()"))
    elif icon == "copy":
        ACTION.setShortcut(QKeySequence.Copy)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("copy()"))
    elif icon == "paste":
        ACTION.setShortcut(QKeySequence.Paste)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("paste()"))

    elif icon == "windowcascade":
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("cascade()"))
    elif icon == "windowtile":
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("tile()"))
    elif icon == "windowclose":
        ACTION.setShortcut(QKeySequence.Close)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("onCloseWindow()"))
    elif icon == "windowcloseall":
        connect(ACTION, SIGNAL("triggered()"), mdiArea,
                SLOT("closeAllSubWindows()"))
    elif icon == "windownext":
        ACTION.setShortcut(QKeySequence.NextChild)
        connect(ACTION, SIGNAL("triggered()"), mdiArea,
                SLOT("activateNextSubWindow()"))
    elif icon == "windowprevious":
        ACTION.setShortcut(QKeySequence.PreviousChild)
        connect(ACTION, SIGNAL("triggered()"), mdiArea,
                SLOT("activatePreviousSubWindow()"))

    elif icon == "help":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("help()"))
    elif icon == "changelog":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("changelog()"))
    elif icon == "tipoftheday":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("tipOfTheDay()"))
    elif icon == "about":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("about()"))
    elif icon == "whatsthis":
        connect(ACTION, SIGNAL("triggered()"), self,
                SLOT("whatsThisContextHelp()"))

    elif icon == "icon16":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon16()"))
    elif icon == "icon24":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon24()"))
    elif icon == "icon32":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon32()"))
    elif icon == "icon48":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon48()"))
    elif icon == "icon64":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon64()"))
    elif icon == "icon128":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon128()"))

    elif icon == "settingsdialog":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("settingsDialog()"))

    elif icon == "undo":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("undo()"))
    elif icon == "redo":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("redo()"))

    elif icon == "makelayercurrent":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("makeLayerActive()"))
    elif icon == "layers":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerManager()"))
    elif icon == "layerprevious":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerPrevious()"))

    elif icon == "textbold":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self,
                SLOT("setTextBold(bool)"))
    elif icon == "textitalic":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self,
                SLOT("setTextItalic(bool)"))
    elif icon == "textunderline":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self,
                SLOT("setTextUnderline(bool)"))
    elif icon == "textstrikeout":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self,
                SLOT("setTextStrikeOut(bool)"))
    elif icon == "textoverline":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self,
                SLOT("setTextOverline(bool)"))

    elif icon == "zoomrealtime":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomRealtime()"))
    elif icon == "zoomprevious":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomPrevious()"))
    elif icon == "zoomwindow":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomWindow()"))
    elif icon == "zoomdynamic":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomDynamic()"))
    elif icon == "zoomscale":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomScale()"))
    elif icon == "zoomcenter":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomCenter()"))
    elif icon == "zoomin":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomIn()"))
    elif icon == "zoomout":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomOut()"))
    elif icon == "zoomselected":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomSelected()"))
    elif icon == "zoomall":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomAll()"))
    elif icon == "zoomextents":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomExtents()"))

    elif icon == "panrealtime":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panrealtime()"))
    elif icon == "panpoint":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panpoint()"))
    elif icon == "panleft":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panLeft()"))
    elif icon == "panright":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panRight()"))
    elif icon == "panup":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panUp()"))
    elif icon == "pandown":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panDown()"))

    elif icon == "day":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("dayVision()"))
    elif icon == "night":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("nightVision()"))

    elif scripted:
        ACTION.setIcon(
            QIcon(self.gAppDir + os.sep + "commands/" + icon + "/" + icon +
                  ".png"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("runCommand()"))

    else:
        ACTION.setEnabled(False)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("stub_implement()"))

    return ACTION
Beispiel #8
0
    def contextMenuEvent(self, event):
        """
        Handles the ``contextMenuEvent`` event for :class:`StatusBarButton`.

        :param `event`: A `QContextMenuEvent`_ to be processed.
        """
        QApplication.setOverrideCursor(Qt.ArrowCursor)
        menu = QMenu(self)
        objName = self.objectName()
        themeDir = gIconDir + os.sep + '..' + os.sep + self.mainWin.getSettingsGeneralIconTheme(
        ) + os.sep
        s = "&Settings..."
        if objName == "StatusBarButtonSNAP":

            settingsSnapAction = QAction(
                QIcon(themeDir + "gridsnapsettings.png"), s, menu)
            settingsSnapAction.triggered.connect(self.settingsSnap)
            menu.addAction(settingsSnapAction)

        elif objName == "StatusBarButtonGRID":

            settingsGridAction = QAction(QIcon(themeDir + "gridsettings.png"),
                                         s, menu)
            settingsGridAction.triggered.connect(self.settingsGrid)
            menu.addAction(settingsGridAction)

        elif objName == "StatusBarButtonRULER":

            settingsRulerAction = QAction(
                QIcon(themeDir + "rulersettings.png"), s, menu)
            settingsRulerAction.triggered.connect(self.settingsRuler)
            menu.addAction(settingsRulerAction)

        elif objName == "StatusBarButtonORTHO":

            settingsOrthoAction = QAction(
                QIcon(themeDir + "orthosettings.png"), s, menu)
            settingsOrthoAction.triggered.connect(self.settingsOrtho)
            menu.addAction(settingsOrthoAction)

        elif objName == "StatusBarButtonPOLAR":

            settingsPolarAction = QAction(
                QIcon(themeDir + "polarsettings.png"), s, menu)
            settingsPolarAction.triggered.connect(self.settingsPolar)
            menu.addAction(settingsPolarAction)

        elif objName == "StatusBarButtonQSNAP":

            settingsQSnapAction = QAction(
                QIcon(themeDir + "qsnapsettings.png"), s, menu)
            settingsQSnapAction.triggered.connect(self.settingsQSnap)
            menu.addAction(settingsQSnapAction)

        elif objName == "StatusBarButtonQTRACK":

            settingsQTrackAction = QAction(
                QIcon(themeDir + "qtracksettings.png"), s, menu)
            settingsQTrackAction.triggered.connect(self.settingsQTrack)
            menu.addAction(settingsQTrackAction)

        elif objName == "StatusBarButtonLWT":

            gview = self.mainWin.activeView()
            if gview:

                enableRealAction = QAction(QIcon(themeDir + "realrender.png"),
                                           "&RealRender On", menu)
                enableRealAction.setEnabled(not gview.isRealEnabled())
                enableRealAction.triggered.connect(self.enableReal)
                menu.addAction(enableRealAction)

                disableRealAction = QAction(QIcon(themeDir + "realrender.png"),
                                            "&RealRender Off", menu)
                disableRealAction.setEnabled(gview.isRealEnabled())
                disableRealAction.triggered.connect(self.disableReal)
                menu.addAction(disableRealAction)

            settingsLwtAction = QAction(
                QIcon(themeDir + "lineweightsettings" + ".png"), s, menu)
            settingsLwtAction.triggered.connect(self.settingsLwt)
            menu.addAction(settingsLwtAction)

        menu.exec_(event.globalPos())
        QApplication.restoreOverrideCursor()
        self.statusbar.clearMessage()
Beispiel #9
0
class MainWindow(QMainWindow):
    start_acq = Signal(str)
    start_rec = Signal(str)
    collect_frame = Signal(object)
    collect_threshed = Signal(object)

    def __init__(self, parent=None):
        ''' sets up the whole main window '''

        #standard init
        super(MainWindow, self).__init__(parent)

        #set the window title
        self.setWindowTitle('Open Ephys Control GUI')

        self.window_height = 700
        self.window_width = 1100

        self.screen2 = QDesktopWidget().screenGeometry(0)
        self.move(
            self.screen2.left() +
            (self.screen2.width() - self.window_width) / 2.,
            self.screen2.top() +
            (self.screen2.height() - self.window_height) / 2.)

        self.get_info()
        self.noinfo = True

        while self.noinfo:
            loop = QEventLoop()
            QTimer.singleShot(500., loop.quit)
            loop.exec_()

        subprocess.Popen('start %s' % open_ephys_path, shell=True)

        self.collect_frame.connect(self.update_frame)
        self.collect_threshed.connect(self.update_threshed)
        self.acquiring = False
        self.recording = False

        self.video_height = self.window_height * .52
        self.video_width = self.window_width * .48

        self.resize(self.window_width, self.window_height)

        #create QTextEdit window 'terminal' for receiving stdout and stderr
        self.terminal = QTextEdit(self)
        #set the geometry
        self.terminal.setGeometry(
            QRect(self.window_width * .02,
                  self.window_height * .15 + self.video_height,
                  self.video_width * .96, 150))

        #make widgets
        self.setup_video_frames()
        self.setup_thresh_buttons()

        self.overlay = True

        #create thread and worker for video processing
        self.videoThread = QThread(self)
        self.videoThread.start()
        self.videoproc_worker = VideoWorker(self)
        self.videoproc_worker.moveToThread(self.videoThread)

        self.vt_file = None
        """""" """""" """""" """""" """""" """""" """""" """
        set up menus
        """ """""" """""" """""" """""" """""" """""" """"""

        #create a QMenuBar and set geometry
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(
            QRect(0, 0, self.window_width * .5, self.window_height * .03))
        #set the QMenuBar as menu bar for main window
        self.setMenuBar(self.menubar)

        #create a QStatusBar
        statusbar = QStatusBar(self)
        #set it as status bar for main window
        self.setStatusBar(statusbar)

        #create icon toolbar with default image
        iconToolBar = self.addToolBar("iconBar.png")

        #create a QAction for the acquire button
        self.action_Acq = QAction(self)
        #make it checkable
        self.action_Acq.setCheckable(True)
        #grab an icon for the button
        acq_icon = self.style().standardIcon(QStyle.SP_MediaPlay)
        #set the icon for the action
        self.action_Acq.setIcon(acq_icon)
        #when the button is pressed, call the Acquire function
        self.action_Acq.triggered.connect(self.Acquire)

        #create a QAction for the record button
        self.action_Record = QAction(self)
        #make it checkable
        self.action_Record.setCheckable(True)
        #grab an icon for the button
        record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton)
        #set the icon for the action
        self.action_Record.setIcon(record_icon)
        #when the button is pressed, call advanced_settings function
        self.action_Record.triggered.connect(self.Record)

        #create QAction for stop button
        action_Stop = QAction(self)
        #grab close icon
        stop_icon = self.style().standardIcon(QStyle.SP_MediaStop)
        #set icon for action
        action_Stop.setIcon(stop_icon)
        #when button pressed, close window
        action_Stop.triggered.connect(self.Stop)

        #show tips for each action in the status bar
        self.action_Acq.setStatusTip("Start acquiring")
        self.action_Record.setStatusTip("Start recording")
        action_Stop.setStatusTip("Stop acquiring/recording")

        #add actions to icon toolbar
        iconToolBar.addAction(self.action_Acq)
        iconToolBar.addAction(self.action_Record)
        iconToolBar.addAction(action_Stop)

        #        self.sort_button = QPushButton('Sort Now',self)
        #        self.sort_button.setGeometry(QRect(self.window_width*.85,0,self.window_width*.15,self.window_height*.05))
        #        self.sort_button.clicked.connect(self.sort_now)

        #show the window if minimized by windows
        self.showMinimized()
        self.showNormal()
        """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" ""
        """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" ""

    #this function acts as a slot to accept 'message' signal
    @Slot(str)
    def print_message(self, message):
        ''' print stdout and stderr to terminal window '''

        #move terminal cursor to end
        self.terminal.moveCursor(QTextCursor.End)
        #write message to terminal
        self.terminal.insertPlainText(message)

    def setup_thresh_buttons(self):
        ''' set up buttons for overlay/clearing thresh view '''

        self.button_frame = QFrame(self)
        self.button_frame.setGeometry(
            QRect(self.window_width * .52,
                  self.window_height * .13 + self.video_height,
                  self.video_width * .98, 50))
        button_layout = QHBoxLayout()
        self.button_frame.setLayout(button_layout)
        self.clear_button = QPushButton('Clear')
        self.overlay_button = QPushButton('Overlay')
        button_layout.addWidget(self.clear_button)
        button_layout.addWidget(self.overlay_button)

        self.clear_button.setEnabled(False)
        self.clear_button.clicked.connect(self.clear_threshed)
        self.overlay_button.setEnabled(False)
        self.overlay_button.clicked.connect(self.overlay_threshed)

    def setup_video_frames(self):
        ''' set up spots for playing video frames '''

        filler_frame = np.zeros((360, 540, 3))
        filler_frame = qimage2ndarray.array2qimage(filler_frame)

        self.raw_frame = QFrame(self)
        self.raw_label = QLabel()
        self.raw_label.setText('raw')
        self.raw_frame.setGeometry(
            QRect(self.window_width * .01, self.window_height * .15,
                  self.video_width, self.video_height))
        self.raw_frame
        raw_layout = QVBoxLayout()
        self.raw_frame.setLayout(raw_layout)
        raw_layout.addWidget(self.raw_label)

        self.threshed_frame = QFrame(self)
        self.threshed_label = QLabel()
        self.threshed_label.setText('Threshed')
        self.threshed_frame.setGeometry(
            QRect(self.window_width * .51, self.window_height * .15,
                  self.video_width, self.video_height))
        threshed_layout = QVBoxLayout()
        self.threshed_frame.setLayout(threshed_layout)
        threshed_layout.addWidget(self.threshed_label)

        self.label_frame = QFrame(self)
        self.label_frame.setGeometry(
            QRect(self.window_width * .01, self.window_height * .11,
                  self.video_width * 2, 50))
        self.label_rawlabel = QLabel()
        self.label_rawlabel.setText('Raw Video')
        self.label_threshedlabel = QLabel()
        self.label_threshedlabel.setText('Threshold View')
        label_layout = QHBoxLayout()
        self.label_frame.setLayout(label_layout)
        label_layout.addWidget(self.label_rawlabel)
        label_layout.addWidget(self.label_threshedlabel)

        self.raw_label.setPixmap(QPixmap.fromImage(filler_frame))
        self.threshed_label.setPixmap(QPixmap.fromImage(filler_frame))

    def Acquire(self):

        if self.action_Acq.isChecked():

            self.vidbuffer = []

            if self.recording:

                while 1:
                    try:
                        self.sock.send('StopRecord')
                        self.sock.recv()
                    except:
                        continue
                    break

                self.recording = False

            else:
                #create and start a thread to transport a worker to later
                self.workerThread = QThread(self)
                self.workerThread.start()
                #create a worker object based on Worker class and move it to our
                #worker thread
                self.worker = Worker(self)
                self.worker.moveToThread(self.workerThread)

                try:
                    self.start_acq.disconnect()
                except:
                    pass

                while 1:
                    try:
                        self.sock.send('StartAcquisition')
                        self.sock.recv()
                    except:
                        continue
                    break

                self.acquiring = True
                self.start_acq.connect(self.worker.acquire)
                self.start_acq.emit('start!')

            self.action_Acq.setEnabled(False)
            self.action_Record.setChecked(False)
            self.action_Record.setEnabled(True)

            record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton)
            #set the icon for the action
            self.action_Record.setIcon(record_icon)

    def Record(self):

        if self.action_Record.isChecked():

            if not self.acquiring:
                self.workerThread = QThread(self)
                self.workerThread.start()

                self.worker = Worker(self)
                self.worker.moveToThread(self.workerThread)

                try:
                    self.start_rec.disconnect()
                except:
                    pass

                while 1:
                    try:
                        self.sock.send('StartAcquisition')
                        self.sock.recv()
                    except:
                        continue
                    break

                while 1:
                    try:
                        self.sock.send('StartRecord')
                        self.sock.recv()
                    except:
                        continue
                    break

                self.vidbuffer = []
                self.start_rec.connect(self.worker.acquire)
                self.recording = True
                self.start_rec.emit('start!')

            else:

                while 1:
                    try:
                        self.sock.send('StartRecord')
                        self.sock.recv()
                    except:
                        continue
                    break

                self.vidbuffer = []
                self.recording = True

            record_icon = self.style().standardIcon(QStyle.SP_DialogNoButton)
            #set the icon for the action
            self.action_Record.setIcon(record_icon)
            self.action_Record.setEnabled(False)

            self.action_Acq.setChecked(False)
            self.action_Acq.setEnabled(True)

    def Stop(self):

        self.acquiring = False
        self.recording = False

        while 1:
            try:
                self.sock.send('isRecording')
                rec = self.sock.recv()
            except:
                continue
            break

        if rec == '1':
            while 1:
                try:
                    self.sock.send('StopRecord')
                    self.sock.recv()
                except:
                    continue
                break

            self.action_Record.setEnabled(True)
            self.action_Record.setChecked(False)

        while 1:
            try:
                self.sock.send('isAcquiring')
                acq = self.sock.recv_string()
            except:
                continue
            break

        if acq == '1':
            while 1:
                try:
                    self.sock.send('StopAcquisition')
                    self.sock.recv()
                except:
                    continue
                break

        self.action_Acq.setEnabled(True)
        self.action_Acq.setChecked(False)

        try:
            #open a csv file for saving tracking data
            with open(self.vt_file, 'a') as csvfile:
                #create a writer
                vidwriter = csv.writer(csvfile, dialect='excel-tab')
                #check if it's an empty file
                for row in self.vidbuffer:
                    vidwriter.writerow(row)

        except:
            pass

        record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton)
        #set the icon for the action
        self.action_Record.setIcon(record_icon)

    def update_frame(self, image):
        self.raw_label.setPixmap(QPixmap.fromImage(image))

    def update_threshed(self, threshed_image):
        self.threshed_label.setPixmap(QPixmap.fromImage(threshed_image))

    def clear_threshed(self):
        self.green_frame = np.zeros_like(self.green_frame)
        self.red_frame = np.zeros_like(self.red_frame)

    def overlay_threshed(self):
        if self.overlay:
            self.overlay = False
        elif not self.overlay:
            self.overlay = True


#    def sort_now(self):
#
#        if self.recdir is not None:
#            os.chdir('./kilosort_control')
#            #create and show the main window
#            self.sort_frame = kilosort_control.sort_gui.MainWindow()
#            self.sort_frame.show()
#
#            #set up stream for stdout and stderr based on outputStream class
#            self.outputStream = kilosort_control.sort_gui.outputStream()
#            #when outputStream sends messages, connect to appropriate function for
#            #writing to terminal window
#            self.outputStream.message.connect(self.sort_frame.print_message)
#
#            #connect stdout and stderr to outputStream
#            sys.stdout = self.outputStream
#            sys.stderr = self.outputStream
#
#            self.sort_frame.run_now(self.recdir)
#
#            self.close()

    def get_info(self):

        self.info_window = QWidget()
        self.info_window.resize(400, 350)
        #set title
        self.info_window.setWindowTitle('Session Info')
        #give layout
        info_layout = QVBoxLayout(self.info_window)

        with open('info_fields.pickle', 'rb') as f:
            default_fields = pickle.load(f)
            f.close()

        #set label for pic_resolution setting
        experimenter_label = QLabel('Experimenter:')
        #make a QLineEdit box for displaying/editing settings
        experimenter = QComboBox(self.info_window)
        experimenter.setEditable(True)
        experimenter.addItems(default_fields['experimenter'])
        #add label and box to current window
        info_layout.addWidget(experimenter_label)
        info_layout.addWidget(experimenter)

        #set label for pic_resolution setting
        whose_animal_label = QLabel('Whose animal?')
        #make a QLineEdit box for displaying/editing settings
        whose_animal = QComboBox(self.info_window)
        whose_animal.setEditable(True)
        whose_animal.addItems(default_fields['whose_animal'])
        #add label and box to current window
        info_layout.addWidget(whose_animal_label)
        info_layout.addWidget(whose_animal)

        animal_number_label = QLabel('Animal number:')
        animal_number = QComboBox(self.info_window)
        animal_number.setEditable(True)
        animal_number.addItems(default_fields['animal_number'])
        info_layout.addWidget(animal_number_label)
        info_layout.addWidget(animal_number)

        session_number_label = QLabel('Session number:')
        session_number = QTextEdit(self.info_window)
        session_number.setText('1')
        info_layout.addWidget(session_number_label)
        info_layout.addWidget(session_number)

        session_type_label = QLabel('Session type:')
        session_type = QComboBox(self.info_window)
        session_type.setEditable(True)
        session_type.addItems(default_fields['session_type'])
        info_layout.addWidget(session_type_label)
        info_layout.addWidget(session_type)

        def save_info(self):

            info_fields = {}
            info_fields['experimenter'] = [
                experimenter.itemText(i) for i in range(experimenter.count())
            ]
            info_fields['whose_animal'] = [
                whose_animal.itemText(i) for i in range(whose_animal.count())
            ]
            info_fields['animal_number'] = [
                animal_number.itemText(i) for i in range(animal_number.count())
            ]
            info_fields['session_type'] = [
                session_type.itemText(i) for i in range(session_type.count())
            ]

            with open('info_fields.pickle', 'wb') as f:
                pickle.dump(info_fields, f, protocol=2)
                f.close()

            current_experimenter = str(experimenter.currentText())
            current_whose_animal = str(whose_animal.currentText())
            current_animal_number = str(animal_number.currentText())
            current_session_number = str(session_number.toPlainText())
            current_session_type = str(session_type.currentText())

            recdir = data_save_dir + current_whose_animal + '/' + current_animal_number

            if not os.path.exists(recdir):
                os.makedirs(recdir)

            self.experiment_info = '###### Experiment Info ######\r\n'
            self.experiment_info += 'Experimenter: %s\r\n' % current_experimenter
            self.experiment_info += 'Whose animal? %s\r\n' % current_whose_animal
            self.experiment_info += 'Animal number: %s\r\n' % current_animal_number
            self.experiment_info += 'Session number: %s\r\n' % current_session_number
            self.experiment_info += 'Session type: %s\r\n' % current_session_type

            self.experiment_info = self.experiment_info.encode()

            config_file = config_path + '/' + current_animal_number + '.xml'

            if not os.path.exists(config_file):
                shutil.copy(default_config, config_file)

            tree = et.parse(config_file)
            root = tree.getroot()
            for child in root:
                if child.tag == 'CONTROLPANEL':
                    child.attrib['recordPath'] = recdir.replace('/', '\\')
            tree.write(config_file)
            tree.write(default_config)

            self.info_window.close()
            self.noinfo = False

        ready_button = QPushButton('Ready!')
        ready_button.clicked.connect(lambda: save_info(self))
        info_layout.addWidget(ready_button)

        self.info_window.show()
Beispiel #10
0
class STMainWindow(QMainWindow):
    def __init__(self):
        super(STMainWindow, self).__init__()
        self.createActions()
        self.createMenus()
        layout = QVBoxLayout()
        self.tabs = QTabWidget()
        self.tabs.setTabPosition(QTabWidget.West)
        self.tabs.currentChanged[int].connect(self.tabChanged)
        self.sessiontab = sweattrails.qt.sessiontab.SessionTab(self)
        self.tabs.addTab(self.sessiontab, "Sessions")
        self.tabs.addTab(sweattrails.qt.fitnesstab.FitnessTab(self),
                         "Fitness")
        self.tabs.addTab(sweattrails.qt.profiletab.ProfileTab(self),
                         "Profile")
        self.usertab = sweattrails.qt.usertab.UserTab(self)
        self.tabs.addTab(self.usertab, "Users")
        self.usertab.hide()
        layout.addWidget(self.tabs)
        w = QWidget(self)
        w.setLayout(layout)
        self.setCentralWidget(w)
        self.statusmessage = QLabel()
        self.statusmessage.setMinimumWidth(200)
        self.statusBar().addPermanentWidget(self.statusmessage)
        self.progressbar = QProgressBar()
        self.progressbar.setMinimumWidth(100)
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.statusBar().addPermanentWidget(self.progressbar)
        self.setWindowTitle("SweatTrails")
        self.setWindowIconText("SweatTrails")
        icon = QPixmap("image/sweatdrops.png")
        self.setWindowIcon(QIcon(icon))
        QCoreApplication.instance().refresh.connect(self.userSet)


    def createActions(self):
        self.switchUserAct = QAction("&Switch User", self, shortcut = "Ctrl+U", statusTip = "Switch User", triggered = self.switch_user)
        self.importFileAct = QAction("&Import", self, shortcut = "Ctrl+I", statusTip = "Import Session", triggered = self.file_import)
        self.downloadAct = QAction("&Download", self, shortcut = "Ctrl+D",
                                   statusTip = "Download activities from device",
                                   triggered = QCoreApplication.instance().download)
        self.downloadAct = QAction("&Withings", self,
                                   statusTip = "Download Withings data",
                                   triggered = QCoreApplication.instance().withings)
        self.exitAct = QAction("E&xit", self, shortcut = "Ctrl+Q", statusTip = "Exit SweatTrails", triggered = self.close)

        self.aboutAct = QAction("&About", self, triggered = self.about)
        self.aboutQtAct = QAction("About &Qt", self, triggered = QApplication.aboutQt)


    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu(self.tr("&File"))
        self.fileMenu.addAction(self.switchUserAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.importFileAct)
        self.fileMenu.addAction(self.downloadAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)


    def show(self):
        super(QMainWindow, self).show()
        if self.select_user():
            t = sweattrails.qt.imports.BackgroundThread.get_thread()
            t.jobStarted.connect(self.status_message)
            t.jobFinished.connect(self.status_message)
            t.jobError.connect(self.status_message)
        else:
            self.close()

    def switch_user(self):
        pass

    def select_user(self):
        ret = False
        if QCoreApplication.instance().user:
            return True
        elif QCoreApplication.instance().has_users():
            dialog = SelectUser(self)
            dialog.select()
            ret = QCoreApplication.instance().is_authenticated()
            if ret:
                self.refresh()
        else:
            dialog = CreateUser(self)
            dialog.exec_()
            ret = QCoreApplication.instance().is_authenticated()
            if ret:
                self.refresh()
        return ret

    #
    # FILE IMPORT
    #

    def file_import(self):
        (fileNames, _) = QFileDialog.getOpenFileNames(self,
                               "Open Activity File",
                               "",
                               "Activity Files (*.tcx *.fit *.csv)")
        if fileNames:
            QCoreApplication.instance().import_files(*fileNames)

    def file_import_started(self, filename):
        self.switchUserAct.setEnabled(False)

    def file_imported(self, filename):
        self.switchUserAct.setEnabled(True)
        self.refresh()

    def file_import_error(self, filename, msg):
        self.switchUserAct.setEnabled(True)
        self.refresh()

    #
    # END FILE IMPORT
    #

    # =====================================================================
    # S I G N A L  H A N D L E R S
    # =====================================================================

    def refresh(self):
        QCoreApplication.instance().refresh.emit()
        self.status_message("")

    def tabChanged(self, tabix):
        w = self.tabs.currentWidget()
        if hasattr(w, "activate"):
            w.activate(0)
        if hasattr(w, "setValues"):
            w.setValues()

    def setSession(self, session):
        self.tabs.setCurrentIndex(0)
        self.sessiontab.setSession(session)

    def setTab(self, tab):
        t = self.tabs.currentWidget()
        if t and hasattr(t, "setTab"):
            t.setTab(tab)

    def userSet(self):
        user = QCoreApplication.instance().user
        if user.is_admin():
            self.usertab.show()

    def status_message(self, msg, *args):
        self.statusmessage.setText(msg.format(*args))

    def progress_init(self, msg, *args):
        self.progressbar.setValue(0)
        self.status_message(msg, *args)

    def progress(self, percentage):
        self.progressbar.setValue(percentage)

    def progress_done(self):
        self.progressbar.reset()

    def about(self):
        QMessageBox.about(self, "About SweatTrails",
                          "SweatTrails is a training log application")
Beispiel #11
0
class MainWindow(QtGui.QMainWindow):
    """The application's main window
    """
    FILE_FILTER = "inselect files (*{0})".format(InselectDocument.EXTENSION)

    def __init__(self, app, filename=None):
        super(MainWindow, self).__init__()
        self.app = app

        # Boxes view
        self.view_graphics_item = GraphicsItemView()
        # self.boxes_view is a QGraphicsView, not a QAbstractItemView
        self.boxes_view = BoxesView(self.view_graphics_item.scene)

        # Metadata view
        self.view_specimen = SpecimenView()
        self.view_metadata = MetadataView()

        self.specimens = QtGui.QSplitter()
        self.specimens.addWidget(self.view_specimen)
        self.specimens.addWidget(self.view_metadata.widget)
        self.specimens.setSizes([600, 300])

        # Views in tabs
        self.tabs = QtGui.QTabWidget(self)
        self.tabs.addTab(self.boxes_view, 'Boxes')
        self.tabs.addTab(self.specimens, 'Specimens')
        self.tabs.setCurrentIndex(0)

        # Summary view
        self.view_summary = SummaryView()

        # Main window layout
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.view_summary.widget)
        layout.addWidget(self.tabs)
        box = QtGui.QWidget()
        box.setLayout(layout)
        self.setCentralWidget(box)

        # Document
        self.document = None
        self.document_path = None

        # Model
        self.model = Model()
        self.view_graphics_item.setModel(self.model)
        self.view_specimen.setModel(self.model)
        self.view_metadata.setModel(self.model)
        self.view_summary.setModel(self.model)

        # A consistent selection across all views
        sm = self.view_specimen.selectionModel()
        self.view_graphics_item.setSelectionModel(sm)
        self.view_metadata.setSelectionModel(sm)
        self.view_summary.setSelectionModel(sm)

        # Plugins
        self.plugins = [SegmentPlugin, SubsegmentPlugin, BarcodePlugin]
        self.plugin_actions = len(self.plugins) * [None]  # QActions
        self.plugin_image = None
        self.plugin_image_visible = False

        # Long-running operations are run in their own thread.
        self.running_operation = None

        self.create_actions()
        self.create_menus()

        # Conect signals
        self.tabs.currentChanged.connect(self.current_tab_changed)
        sm.selectionChanged.connect(self.selection_changed)

        # Filter events
        self.tabs.installEventFilter(self)
        self.boxes_view.installEventFilter(self)
        self.view_specimen.installEventFilter(self)
        self.view_metadata.installEventFilter(self)

        self.empty_document()

        self.setAcceptDrops(True)

        if filename:
            self.open_file(filename)

    def eventFilter(self, obj, event):
        if event.type() in (QEvent.DragEnter, QEvent.Drop):
            return True
        else:
            return super(MainWindow, self).eventFilter(obj, event)

    @report_to_user
    def open_file(self, path=None):
        """Opens path, which can be None, the path to an inselect document or
        the path to an image file. If None, the user is prompted to select a
        file.

        * If a .inselect file, the file is opened
        * If an image file for which a .inselect document already exists, the
        .inselect file is opened
        * If a _thumbnail.jpg file corresponding to an existing .inselect file,
        the .inselect file is opened
        * If an image file, a new .inselect file is created and opened
        """
        debug_print(u'MainWindow.open_file [{0}]'.format(path))

        if not path:
            folder = QSettings().value(
                'working_directory',
                QDesktopServices.storageLocation(
                    QDesktopServices.DocumentsLocation))

            filter = u'Inselect documents (*{0});;Images ({1})'
            filter = filter.format(InselectDocument.EXTENSION,
                                   u' '.join(IMAGE_PATTERNS))
            path, selectedFilter = QtGui.QFileDialog.getOpenFileName(
                self, "Open", folder, filter)

        if path:
            # Will be None if user cancelled getOpenFileName
            if not self.close_document():
                # User does not want to close the existing document
                pass
            else:
                path = Path(path)

                if path.suffix in IMAGE_SUFFIXES:
                    # Compute the path to the inselect document (which may or
                    # may not already exist) of the image file
                    doc_of_image = path.name.replace(
                        InselectDocument.THUMBNAIL_SUFFIX, u'')
                    doc_of_image = path.parent / doc_of_image
                    doc_of_image = doc_of_image.with_suffix(
                        InselectDocument.EXTENSION)
                else:
                    doc_of_image = None

                if InselectDocument.EXTENSION == path.suffix:
                    # Open the .inselect document
                    debug_print('Opening inselect document [{0}]'.format(path))
                    self.open_document(path)
                elif doc_of_image and doc_of_image.is_file():
                    # An image file corresponding to an existing .inselect file
                    msg = u'Opening inselect document [{0}] of thumbnail [{1}]'
                    debug_print(msg.format(doc_of_image, path))
                    self.open_document(doc_of_image)
                elif path.suffix in IMAGE_SUFFIXES:
                    msg = u'Creating new inselect document for image [{0}]'
                    debug_print(msg.format(path))
                    self.new_document(path)
                else:
                    raise InselectError('Unknown file type [{0}]'.format(path))

    def new_document(self, path):
        """Creates and opens a new inselect document for the scanned image
        given in path
        """
        debug_print('MainWindow.new_document [{0}]'.format(path))

        path = Path(path)
        if not path.is_file():
            raise InselectError(
                u'Image file [{0}] does not exist'.format(path))
        else:
            # Callable for worker thread
            class NewDoc(object):
                def __init__(self, image):
                    self.image = image

                def __call__(self, progress):
                    progress('Creating thumbnail of scanned image')
                    doc = ingest_image(self.image, self.image.parent)
                    self.document_path = doc.document_path

            self.run_in_worker(NewDoc(path), 'New document',
                               self.new_document_finished)

    def new_document_finished(self, operation):
        """Called when new_document worker has finished
        """
        debug_print('MainWindow.new_document_finished')

        document_path = operation.document_path
        QSettings().setValue('working_directory', str(document_path.parent))

        self.open_file(document_path)
        msg = u'New Inselect document [{0}] created in [{1}]'
        msg = msg.format(document_path.stem, document_path.parent)
        QMessageBox.information(self, "Document created", msg)

    def open_document(self, path):
        """Opens the inselect document given by path
        """
        debug_print('MainWindow.open_document [{0}]'.format(path))

        path = Path(path)
        document = InselectDocument.load(path)
        QSettings().setValue("working_directory", str(path.parent))

        self.document = document
        self.document_path = path
        self.model.from_document(self.document)

        # TODO LH Prefer setWindowFilePath to setWindowTitle?
        self.setWindowTitle(u"Inselect [{0}]".format(self.document_path.stem))

        self.sync_ui()

    @report_to_user
    def save_document(self):
        """Saves the document
        """
        debug_print('MainWindow.save_document')
        items = []

        self.model.to_document(self.document)
        self.document.save()
        self.model.clear_modified()

    @report_to_user
    def save_crops(self):
        """Saves cropped specimen images
        """
        debug_print('MainWindow.save_crops')
        res = QMessageBox.Yes
        existing_crops = self.document.crops_dir.is_dir()

        if existing_crops:
            msg = 'Overwrite the existing cropped specimen images?'
            res = QMessageBox.question(self, 'Write cropped specimen images?',
                                       msg, QMessageBox.No, QMessageBox.Yes)

        if QMessageBox.Yes == res:

            def save_crops(progress):
                progress('Loading full-resolution scanned image')
                self.document.scanned.array

                progress('Saving crops')
                self.document.save_crops(progress)

            def completed(operation):
                QMessageBox.information(self, "Crops saved", msg)

            self.model.to_document(self.document)
            msg = "{0} crops saved in {1}"
            msg = msg.format(self.document.n_items, self.document.crops_dir)
            self.run_in_worker(save_crops, 'Save crops', completed)

    @report_to_user
    def export_csv(self):
        debug_print('MainWindow.export_csv')

        path = self.document.document_path.with_suffix('.csv')

        res = QMessageBox.Yes
        existing_csv = path.is_file()

        if existing_csv:
            msg = 'Overwrite the existing CSV file?'
            res = QMessageBox.question(self, 'Export CSV file?', msg,
                                       QMessageBox.No, QMessageBox.Yes)

        if QMessageBox.Yes == res:
            self.model.to_document(self.document)
            self.document.export_csv(path)
            msg = "Data for {0} boxes written to {1}"
            msg = msg.format(self.document.n_items, path)
            QMessageBox.information(self, "CSV saved", msg)

    @report_to_user
    def close_document(self):
        """Closes the document and returns True if not modified or if modified
        and user does not cancel. Does not close the document and returns False
        if modified and users cancels.
        """
        debug_print('MainWindow.close_document')
        if self.model.modified:
            # Ask the user if they work like to save before closing
            res = QMessageBox.question(
                self, 'Save document?', 'Save the document before closing?',
                (QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel),
                QMessageBox.Yes)

            if QMessageBox.Yes == res:
                self.save_document()

            # Answering Yes or No means the document will be closed
            close = QMessageBox.Cancel != res
        else:
            # The document is not modified so it is OK to close it
            close = True

        if close:
            self.empty_document()

        return close

    @report_to_user
    def empty_document(self):
        """Creates an empty document
        """
        debug_print('MainWindow.empty_document')
        self.document = None
        self.plugin_image = None
        self.plugin_image_visible = False
        self.model.clear()

        # TODO LH Prefer setWindowFilePath to setWindowTitle?
        self.setWindowTitle("Inselect")

        self.sync_ui()

    def closeEvent(self, event):
        """QWidget virtual
        """
        debug_print('MainWindow.closeEvent')
        if self.close_document():
            # User wants to close
            self.write_geometry_settings()
            event.accept()
        else:
            # User does not want to close
            event.ignore()

    @report_to_user
    def zoom_in(self):
        self.boxes_view.zoom_in()

    @report_to_user
    def zoom_out(self):
        self.boxes_view.zoom_out()

    @report_to_user
    def toggle_zoom(self):
        self.boxes_view.toggle_zoom()

    @report_to_user
    def zoom_home(self):
        self.boxes_view.zoom_home()

    @report_to_user
    def show_grid(self):
        self.view_specimen.show_grid()

    @report_to_user
    def show_expanded(self):
        self.view_specimen.show_expanded()

    @report_to_user
    def about(self):
        text = u"""<h1>Inselect {version}</h1>
           <h2>Contributors</h2>
           <p>
               <strong>Stefan van der Walt</strong>: Application development
               and segmentation algorithm
           </p>
           <p>
               <strong>Pieter Holtzhausen</strong>: Application development
               and segmentation algorithm
           </p>
           <p>
               <strong>Alice Heaton</strong>: Application development
           </p>
           <p>
               <strong>Lawrence Hudson</strong>: Application development
           </p>
        """.format(version=inselect.__version__)
        QMessageBox.about(self, 'Inselect', text)

    @report_to_user
    def help(self):
        """Open the help dialog"""
        d = HelpDialog(self)
        d.exec_()

    def run_in_worker(self, operation, name, complete_fn=None):
        """Runs the callable operation in a worker thread. The callable
        complete_fn is called when the operation has finished.
        """
        debug_print("MainWindow.run_in_worker")

        if self.running_operation:
            debug_print('Operation already running')
        else:
            worker = WorkerThread(operation, name, self)
            worker.completed.connect(self.worker_finished)

            self.running_operation = (operation, name, complete_fn, worker)
            worker.start()

    @report_to_user
    def worker_finished(self, user_cancelled, error_message):
        debug_print("MainWindow.worker_finished", user_cancelled,
                    error_message)

        operation, name, complete_fn, worker = self.running_operation
        self.running_operation = None

        if user_cancelled:
            QMessageBox.information(self, 'Cancelled',
                                    "'{0} cancelled'".format(name))
        elif error_message:
            QMessageBox.information(
                self, "An error occurred running '{0}'".format(name),
                error_message + '\n\nExisting data has not been altered')
        else:
            if complete_fn:
                complete_fn(operation)
            self.sync_ui()

    @report_to_user
    def run_plugin(self, plugin_number):
        """Passes each cropped specimen image through plugin
        """
        debug_print("MainWindow.run_plugin")

        if plugin_number < 0 or plugin_number > len(self.plugins):
            raise ValueError('Unexpected plugin [{0}]'.format(plugin_number))
        else:
            plugin = self.plugins[plugin_number]

            self.model.to_document(self.document)

            # Create the plugin
            operation = plugin(self.document, self)
            if operation.proceed():
                self.run_in_worker(operation, operation.name(),
                                   self.plugin_finished)
            else:
                pass

    def plugin_finished(self, operation):
        """Called when a plugin has finished running in a worker thread
        """
        debug_print("MainWindow.plugin_finished")

        if hasattr(operation, 'items'):
            self.model.set_new_boxes(operation.items)

        if hasattr(operation, 'display'):
            # An image that can be displayed instead of the main image
            display = operation.display
            self.plugin_image = QtGui.QPixmap.fromImage(qimage_of_bgr(display))
            self.update_boxes_display_pixmap()

    @report_to_user
    def select_all(self):
        """Selects all boxes in the model
        """
        sm = self.view_specimen.selectionModel()
        m = self.model
        sm.select(
            QtGui.QItemSelection(m.index(0, 0), m.index(m.rowCount() - 1, 0)),
            QtGui.QItemSelectionModel.Select)

    @report_to_user
    def select_none(self):
        sm = self.view_specimen.selectionModel()
        sm.select(QtGui.QItemSelection(), QtGui.QItemSelectionModel.Clear)

    @report_to_user
    def delete_selected(self):
        """Deletes the selected boxes
        """
        # Delete contiguous blocks of rows
        selected = self.view_specimen.selectionModel().selectedIndexes()
        selected = sorted([i.row() for i in selected])

        # Remove blocks in reverse order so that row indices are not invalidated
        # TODO LH We shouldn't need to remove blocks in reverse order - stems
        # from crummy GraphicsItemView
        for row, count in reversed(list(contiguous(selected))):
            self.model.removeRows(row, count)

    @report_to_user
    def select_next_prev(self, next):
        """Selects the next box in the mode if next is True, the previous
        box in the model if next if False.
        """
        sm = self.view_specimen.selectionModel()
        current = sm.currentIndex()
        current = current.row() if current else -1

        select = current + (1 if next else -1)
        if select == self.model.rowCount():
            select = 0
        elif -1 == select:
            select = self.model.rowCount() - 1

        debug_print('Will move selection [{0}] from [{1}]'.format(
            current, select))
        select = self.model.index(select, 0)
        sm.select(QtGui.QItemSelection(select, select),
                  QtGui.QItemSelectionModel.ClearAndSelect)
        sm.setCurrentIndex(select, QtGui.QItemSelectionModel.Current)

    @report_to_user
    def rotate90(self, clockwise):
        """Rotates the selected boxes 90 either clockwise or counter-clockwise.
        """
        debug_print('MainWindow.rotate')
        value = 90 if clockwise else -90
        selected = self.view_specimen.selectionModel().selectedIndexes()
        for index in selected:
            current = index.data(RotationRole)
            self.model.setData(index, current + value, RotationRole)

    def update_boxes_display_pixmap(self):
        """Sets the pixmap in the boxes view
        """
        pixmap = self.plugin_image if self.plugin_image_visible else None
        self.view_graphics_item.show_alternative_pixmap(pixmap)

    @report_to_user
    def toggle_plugin_image(self):
        """Action method to switch between display of the last plugin's 
        information image (if any) and the actual image.
        """
        self.plugin_image_visible = not self.plugin_image_visible
        self.update_boxes_display_pixmap()

    def create_actions(self):
        # File menu
        self.open_action = QAction("&Open...",
                                   self,
                                   shortcut=QtGui.QKeySequence.Open,
                                   triggered=self.open_file,
                                   icon=self.style().standardIcon(
                                       QtGui.QStyle.SP_DialogOpenButton))
        self.save_action = QAction("&Save",
                                   self,
                                   shortcut=QtGui.QKeySequence.Save,
                                   triggered=self.save_document,
                                   icon=self.style().standardIcon(
                                       QtGui.QStyle.SP_DialogSaveButton))
        self.save_crops_action = QAction("&Save crops",
                                         self,
                                         triggered=self.save_crops)
        self.export_csv_action = QAction("&Export CSV",
                                         self,
                                         triggered=self.export_csv)
        self.close_action = QAction("&Close",
                                    self,
                                    shortcut=QtGui.QKeySequence.Close,
                                    triggered=self.close_document)
        self.exit_action = QAction("E&xit",
                                   self,
                                   shortcut=QtGui.QKeySequence.Quit,
                                   triggered=self.close)

        # Edit menu
        self.select_all_action = QAction("Select &All",
                                         self,
                                         shortcut=QtGui.QKeySequence.SelectAll,
                                         triggered=self.select_all)
        # QT does not provide a 'select none' key sequence
        self.select_none_action = QAction("Select &None",
                                          self,
                                          shortcut="ctrl+D",
                                          triggered=self.select_none)
        self.next_box_action = QAction("Next box",
                                       self,
                                       shortcut="N",
                                       triggered=partial(self.select_next_prev,
                                                         next=True))
        self.previous_box_action = QAction("Previous box",
                                           self,
                                           shortcut="P",
                                           triggered=partial(
                                               self.select_next_prev,
                                               next=False))

        # TODO LH Does CMD + Backspace work on a mac?
        self.delete_action = QAction("&Delete selected",
                                     self,
                                     shortcut=QtGui.QKeySequence.Delete,
                                     triggered=self.delete_selected)
        self.rotate_clockwise_action = QAction("Rotate clockwise",
                                               self,
                                               shortcut="R",
                                               triggered=partial(
                                                   self.rotate90,
                                                   clockwise=True))
        self.rotate_counter_clockwise_action = QAction(
            "Rotate counter-clockwise",
            self,
            shortcut="L",
            triggered=partial(self.rotate90, clockwise=False))

        # Plugins
        # Plugin shortcuts start at F5
        shortcut_offset = 5
        for index, plugin in enumerate(self.plugins):
            action = QAction(plugin.name(),
                             self,
                             triggered=partial(self.run_plugin, index))
            shortcut_fkey = index + shortcut_offset
            if shortcut_fkey < 13:
                # Keyboards typically have 12 function keys
                action.setShortcut('f{0}'.format(shortcut_fkey))
            icon = plugin.icon()
            if icon:
                action.setIcon(icon)
            self.plugin_actions[index] = action

        # View menu
        # The obvious approach is to set the trigger to
        # partial(self.tabs.setCurrentIndex, 0) but this causes a segfault when
        # the application exits on linux.
        self.boxes_view_action = QAction("&Boxes",
                                         self,
                                         checkable=True,
                                         triggered=partial(self.show_tab, 0))
        self.metadata_view_action = QAction("&Specimens",
                                            self,
                                            checkable=True,
                                            triggered=partial(
                                                self.show_tab, 1))

        # FullScreen added in Qt 5.something
        # https://qt.gitorious.org/qt/qtbase-miniak/commit/1ef8a6d
        if not hasattr(QtGui.QKeySequence, 'FullScreen'):
            if 'darwin' == sys.platform:
                KeySequenceFullScreen = 'shift+ctrl+f'
            else:
                KeySequenceFullScreen = 'f11'
        else:
            KeySequenceFullScreen = QtGui.QKeySequence.FullScreen
        self.full_screen_action = QAction("&Full screen",
                                          self,
                                          shortcut=KeySequenceFullScreen,
                                          triggered=self.toggle_full_screen)

        self.zoom_in_action = QAction("Zoom &In",
                                      self,
                                      shortcut=QtGui.QKeySequence.ZoomIn,
                                      triggered=self.zoom_in,
                                      icon=self.style().standardIcon(
                                          QtGui.QStyle.SP_ArrowUp))
        self.zoom_out_action = QAction("Zoom &Out",
                                       self,
                                       shortcut=QtGui.QKeySequence.ZoomOut,
                                       triggered=self.zoom_out,
                                       icon=self.style().standardIcon(
                                           QtGui.QStyle.SP_ArrowDown))
        self.toogle_zoom_action = QAction("&Toogle Zoom",
                                          self,
                                          shortcut='Z',
                                          triggered=self.toggle_zoom)
        self.zoom_home_action = QAction(
            "Fit To Window",
            self,
            shortcut=QtGui.QKeySequence.MoveToStartOfDocument,
            triggered=self.zoom_home)
        # TODO LH Is F3 (normally meaning 'find next') really the right
        # shortcut for the 'toggle plugin image' action?
        self.toggle_plugin_image_action = QAction(
            "&Display plugin image",
            self,
            shortcut="f3",
            triggered=self.toggle_plugin_image,
            statusTip="Display plugin image",
            checkable=True)

        self.show_specimen_grid_action = QAction('Show grid',
                                                 self,
                                                 shortcut='g',
                                                 triggered=self.show_grid)
        self.show_specimen_expanded_action = QAction(
            'Show expanded', self, shortcut='e', triggered=self.show_expanded)

        # Help menu
        self.about_action = QAction("&About", self, triggered=self.about)
        self.help_action = QAction("&Help",
                                   self,
                                   shortcut=QtGui.QKeySequence.HelpContents,
                                   triggered=self.help)

    def create_menus(self):
        self.toolbar = self.addToolBar("Edit")
        self.toolbar.addAction(self.open_action)
        self.toolbar.addAction(self.save_action)
        for action in [a for a in self.plugin_actions if a.icon()]:
            self.toolbar.addAction(action)
        self.toolbar.addAction(self.zoom_in_action)
        self.toolbar.addAction(self.zoom_out_action)
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        self.fileMenu = QMenu("&File", self)
        self.fileMenu.addAction(self.open_action)
        self.fileMenu.addAction(self.save_action)
        self.fileMenu.addAction(self.save_crops_action)
        self.fileMenu.addAction(self.export_csv_action)
        self.fileMenu.addAction(self.close_action)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exit_action)

        self.editMenu = QMenu("&Edit", self)
        self.editMenu.addAction(self.select_all_action)
        self.editMenu.addAction(self.select_none_action)
        self.editMenu.addAction(self.delete_action)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.next_box_action)
        self.editMenu.addAction(self.previous_box_action)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.rotate_clockwise_action)
        self.editMenu.addAction(self.rotate_counter_clockwise_action)
        self.editMenu.addSeparator()
        for action in self.plugin_actions:
            self.editMenu.addAction(action)

        self.viewMenu = QMenu("&View", self)
        self.viewMenu.addAction(self.boxes_view_action)
        self.viewMenu.addAction(self.metadata_view_action)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.full_screen_action)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.zoom_in_action)
        self.viewMenu.addAction(self.zoom_out_action)
        self.viewMenu.addAction(self.toogle_zoom_action)
        self.viewMenu.addAction(self.zoom_home_action)
        self.viewMenu.addAction(self.toggle_plugin_image_action)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.show_specimen_grid_action)
        self.viewMenu.addAction(self.show_specimen_expanded_action)

        self.helpMenu = QMenu("&Help", self)
        self.helpMenu.addAction(self.help_action)
        self.helpMenu.addAction(self.about_action)

        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.editMenu)
        self.menuBar().addMenu(self.viewMenu)
        self.menuBar().addMenu(self.helpMenu)

    def show_tab(self, index):
        self.tabs.setCurrentIndex(index)

    def current_tab_changed(self, index):
        """Slot for self.tabs.currentChanged() signal
        """
        self.sync_ui()

    def selection_changed(self, selected, deselected):
        """Slot for self.grid_view.selectionModel().selectionChanged() signal
        """
        self.sync_ui()

    @report_to_user
    def toggle_full_screen(self):
        """Toggles between full screen and normal
        """
        if self.isFullScreen():
            self.showNormal()
        else:
            self.showFullScreen()

    def _accept_drag_drop(self, event):
        """If event refers to a single file that can opened, returns the path.
        Returns None otherwise.
        """
        urls = event.mimeData().urls() if event.mimeData() else None
        path = Path(urls[0].toLocalFile()) if urls and 1 == len(urls) else None
        if (path and path.suffix in chain([InselectDocument.EXTENSION],
                                          IMAGE_SUFFIXES)):
            return urls[0].toLocalFile()
        else:
            return None

    def dragEnterEvent(self, event):
        """QWidget virtual
        """
        debug_print('MainWindow.dragEnterEvent')
        if self._accept_drag_drop(event):
            event.acceptProposedAction()
        else:
            super(MainWindow, self).dragEnterEvent(event)

    def dropEvent(self, event):
        """QWidget virtual
        """
        debug_print('MainWindow.dropEvent')
        res = self._accept_drag_drop(event)
        if res:
            event.acceptProposedAction()
            self.open_file(res)
        else:
            super(MainWindow, self).dropEvent(event)

    def write_geometry_settings(self):
        "Writes geometry to settings"
        debug_print('MainWindow.write_geometry_settings')

        # Taken from http://stackoverflow.com/a/8736705
        # TODO LH Test on multiple display system
        s = QSettings()

        s.setValue("mainwindow/geometry", self.saveGeometry())
        s.setValue("mainwindow/pos", self.pos())
        s.setValue("mainwindow/size", self.size())

    def show_from_geometry_settings(self):
        debug_print('MainWindow.show_from_geometry_settings')

        # TODO LH What if screen resolution, desktop config change or roaming
        # profile means that restored state is outside desktop?
        s = QSettings()

        self.restoreGeometry(
            s.value("mainwindow/geometry", self.saveGeometry()))
        if not (self.isMaximized() or self.isFullScreen()):
            self.move(s.value("mainwindow/pos", self.pos()))
            self.resize(s.value("mainwindow/size", self.size()))
        self.show()
        # if read_bool("mainwindow/maximized", self.isMaximized()):
        #     debug_print('Will show maximized')
        #     self.showMaximized()
        # elif read_bool("mainwindow/full_screen", self.isMaximized()):
        #     debug_print('Will show full screen')
        #     self.showFullScreen()
        # else:
        #     debug_print('Will show normally')
        #     self.show()

    def sync_ui(self):
        """Synchronise the user interface with the application state
        """
        document = self.document is not None
        has_rows = self.model.rowCount() > 0 if self.model else False
        boxes_view_visible = self.boxes_view == self.tabs.currentWidget()
        specimens_view_visible = self.specimens == self.tabs.currentWidget()
        has_selection = len(self.view_specimen.selectedIndexes()) > 0

        # File
        self.save_action.setEnabled(document)
        self.save_crops_action.setEnabled(has_rows)
        self.export_csv_action.setEnabled(has_rows)
        self.close_action.setEnabled(document)

        # Edit
        self.select_all_action.setEnabled(has_rows)
        self.select_none_action.setEnabled(document)
        self.delete_action.setEnabled(has_selection)
        self.next_box_action.setEnabled(has_rows)
        self.previous_box_action.setEnabled(has_rows)
        self.rotate_clockwise_action.setEnabled(has_selection)
        self.rotate_counter_clockwise_action.setEnabled(has_selection)
        for action in self.plugin_actions:
            action.setEnabled(document)

        # View
        self.boxes_view_action.setChecked(boxes_view_visible)
        self.metadata_view_action.setChecked(not boxes_view_visible)
        self.zoom_in_action.setEnabled(document and boxes_view_visible)
        self.zoom_out_action.setEnabled(document and boxes_view_visible)
        self.toogle_zoom_action.setEnabled(document and boxes_view_visible)
        self.zoom_home_action.setEnabled(document and boxes_view_visible)
        self.toggle_plugin_image_action.setEnabled(document
                                                   and boxes_view_visible)
        self.show_specimen_grid_action.setEnabled(specimens_view_visible)
        self.show_specimen_expanded_action.setEnabled(specimens_view_visible)
Beispiel #12
0
    def __init__(self):
        QMainWindow.__init__(self)

        # the user interface, consisting of a progress bar above a plain
        # text edit, which logs all actions.
        container = QWidget(self)
        container.setLayout(QVBoxLayout(container))
        self.setCentralWidget(container)
        progressbar = QProgressBar(container)
        container.layout().addWidget(progressbar)
        log = QPlainTextEdit(container)
        container.layout().addWidget(log)

        # the actual worker thread
        counter = Counter(100, self)

        # an action to quit the windows
        exit = QAction(QIcon.fromTheme('application-exit'), 'exit', self)

        # add two actions to start and stop the worker to the toolbar of the
        # main window
        start_counting = QAction(QIcon.fromTheme('media-playback-start'),
                                 'Start counting', self)
        stop_counting = QAction(QIcon.fromTheme('media-playback-stop'),
                                'Stop counting', self)
        # initially no counter runs, so we can disable the stop action
        stop_counting.setEnabled(False)

        # add all actions to a toolbar
        actions = self.addToolBar('Actions')
        actions.addAction(exit)
        actions.addSeparator()
        actions.addAction(start_counting)
        actions.addAction(stop_counting)

        # quit the application, if the quit action is triggered
        exit.triggered.connect(QApplication.instance().quit)

        # start and stop the counter, if the corresponding actions are
        # triggered.
        start_counting.triggered.connect(counter.start)
        stop_counting.triggered.connect(counter.stop)

        # adjust the minimum and the maximum of the progress bar, if
        # necessary.  Not really required in this snippet, but added for the
        # purpose of demonstrating it
        counter.minimumChanged.connect(progressbar.setMinimum)
        counter.maximumChanged.connect(progressbar.setMaximum)

        # switch the enabled states of the actions according to whether the
        # worker is running or not
        counter.started.connect(partial(start_counting.setEnabled, False))
        counter.started.connect(partial(stop_counting.setEnabled, True))
        counter.finished.connect(partial(start_counting.setEnabled, True))
        counter.finished.connect(partial(stop_counting.setEnabled, False))

        # update the progess bar continuously
        counter.progress.connect(progressbar.setValue)

        # log all actions in our logging widget
        counter.started.connect(
            partial(self.statusBar().showMessage, 'Counting'))
        counter.finished.connect(partial(self.statusBar().showMessage, 'Done'))
        # log a forced stop
        stop_counting.triggered.connect(partial(log.appendPlainText,
                                                'Stopped'))
        # log all counted values
        counter.progress.connect(lambda v: log.appendPlainText(str(v)))

        # and finally show the current state in the status bar.
        counter.started.connect(partial(log.appendPlainText, 'Counting'))
        counter.finished.connect(partial(log.appendPlainText, 'Done'))
 def _get_menu_header(self, title):
     header = QAction(title, self)
     header.setEnabled(False)
     return header
    def __init__(self):
        QMainWindow.__init__(self)

        # the user interface, consisting of a progress bar above a plain
        # text edit, which logs all actions.
        container = QWidget(self)
        container.setLayout(QVBoxLayout(container))
        self.setCentralWidget(container)
        progressbar = QProgressBar(container)
        container.layout().addWidget(progressbar)
        log = QPlainTextEdit(container)
        container.layout().addWidget(log)

        # the actual worker thread
        counter = Counter(100, self)

        # an action to quit the windows
        exit = QAction(QIcon.fromTheme('application-exit'), 'exit', self)

        # add two actions to start and stop the worker to the toolbar of the
        # main window
        start_counting = QAction(QIcon.fromTheme('media-playback-start'),
                                 'Start counting', self)
        stop_counting = QAction(QIcon.fromTheme('media-playback-stop'),
                                'Stop counting', self)
        # initially no counter runs, so we can disable the stop action
        stop_counting.setEnabled(False)

        # add all actions to a toolbar
        actions = self.addToolBar('Actions')
        actions.addAction(exit)
        actions.addSeparator()
        actions.addAction(start_counting)
        actions.addAction(stop_counting)

        # quit the application, if the quit action is triggered
        exit.triggered.connect(QApplication.instance().quit)

        # start and stop the counter, if the corresponding actions are
        # triggered.
        start_counting.triggered.connect(counter.start)
        stop_counting.triggered.connect(counter.stop)

        # adjust the minimum and the maximum of the progress bar, if
        # necessary.  Not really required in this snippet, but added for the
        # purpose of demonstrating it
        counter.minimumChanged.connect(progressbar.setMinimum)
        counter.maximumChanged.connect(progressbar.setMaximum)

        # switch the enabled states of the actions according to whether the
        # worker is running or not
        counter.started.connect(partial(start_counting.setEnabled, False))
        counter.started.connect(partial(stop_counting.setEnabled, True))
        counter.finished.connect(partial(start_counting.setEnabled, True))
        counter.finished.connect(partial(stop_counting.setEnabled, False))

        # update the progess bar continuously
        counter.progress.connect(progressbar.setValue)

        # log all actions in our logging widget
        counter.started.connect(
            partial(self.statusBar().showMessage, 'Counting'))
        counter.finished.connect(
            partial(self.statusBar().showMessage, 'Done'))
        # log a forced stop
        stop_counting.triggered.connect(
            partial(log.appendPlainText, 'Stopped'))
        # log all counted values
        counter.progress.connect(lambda v: log.appendPlainText(str(v)))

        # and finally show the current state in the status bar.
        counter.started.connect(partial(log.appendPlainText, 'Counting'))
        counter.finished.connect(partial(log.appendPlainText, 'Done'))
class CookieCutterWidget(QWidget):
    "CookieCutter UI"

    FILE_FILTER = u'Inselect cookie cutter (*{0})'.format(
        CookieCutter.EXTENSION
    )

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

        # Configure the UI
        self._create_actions()
        self.button = QPushButton("Cookie cutter")
        self.button.setMaximumWidth(250)
        self.button.setStyleSheet("text-align: left")
        self.popup = QMenu()
        self.inject_actions(self.popup)
        self.button.setMenu(self.popup)

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

    def _create_actions(self):
        self.save_to_new_action = QAction(
            "Save boxes to new cookie cutter...", self
        )
        self.choose_action = QAction(
            "Choose...", self, triggered=self.choose
        )
        self.clear_action = QAction(
            "Do not use a cookie cutter", self, triggered=self.clear
        )
        self.apply_current_action = QAction("Apply", self)

    def inject_actions(self, menu):
        "Adds cookie cutter actions to menu"
        menu.addAction(self.choose_action)
        menu.addAction(self.apply_current_action)
        menu.addSeparator()
        menu.addAction(self.clear_action)
        menu.addSeparator()
        menu.addAction(self.save_to_new_action)

    @report_to_user
    def clear(self):
        "Clears the choice of cookie cutter"
        cookie_cutter_choice().clear()

    @report_to_user
    def choose(self):
        "Shows a 'choose cookie cutter' file dialog"
        debug_print('CookieCutterWidget.choose_cookie_cutter')
        path, selectedFilter = QFileDialog.getOpenFileName(
            self, "Choose cookie cutter",
            unicode(cookie_cutter_choice().last_directory()),
            self.FILE_FILTER
        )

        if path:
            # Save the user's choice
            cookie_cutter_choice().load(path)

    def sync_actions(self, has_document, has_rows):
        "Sync state of actions"
        debug_print('CookieCutterWidget.sync_ui')
        current = cookie_cutter_choice().current
        has_current = cookie_cutter_choice().current is not None
        name = current.name if current else 'Cookie cutter'

        # Truncate text to fit button
        metrics = QFontMetrics(self.button.font())
        elided = metrics.elidedText(
            name, Qt.ElideRight, self.button.width() - 25
        )
        self.button.setText(elided)

        self.save_to_new_action.setEnabled(has_rows)
        self.clear_action.setEnabled(has_current)
        self.apply_current_action.setEnabled(has_document and has_current)
class UserTemplatePopupButton(QPushButton):
    "User template popup button"

    FILE_FILTER = u'Inselect user templates (*{0})'.format(
        UserTemplate.EXTENSION
    )

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

        # Configure the UI
        self._create_actions()
        self.popup = QMenu()
        self.inject_actions(self.popup)
        self.setMenu(self.popup)

        user_template_choice().template_changed.connect(self.changed)

        # User template might already have been loaded so load the initial
        if user_template_choice().current:
            self.changed()

    def __del__(self):
        # Doing this prevents segfault on exit. Unsatisfactory.
        del self.popup

    def _create_actions(self):
        self._choose_action = QAction(
            "Choose...", self, triggered=self.choose
        )
        self._refresh_action = QAction(
            "Reload", self, triggered=self.refresh
        )
        self._default_action = QAction(
            u"Default ({0})".format(user_template_choice().DEFAULT.name),
            self, triggered=self.default
        )

    def inject_actions(self, menu):
        "Adds user template actions to menu"
        menu.addAction(self._choose_action)
        menu.addAction(self._refresh_action)
        menu.addSeparator()
        menu.addAction(self._default_action)

    @report_to_user
    def default(self):
        "Sets the default template"
        user_template_choice().select_default()

    @report_to_user
    def choose(self):
        "Shows a 'choose template' file dialog"
        debug_print('UserTemplateWidget.choose')
        path, selectedFilter = QFileDialog.getOpenFileName(
            self, "Choose user template",
            unicode(user_template_choice().last_directory()),
            self.FILE_FILTER
        )

        if path:
            # Save the user's choice
            user_template_choice().load(path)

    @report_to_user
    def refresh(self):
        debug_print('UserTemplateWidget.refresh')
        user_template_choice().refresh()

    def changed(self):
        "Slot for UserTemplateChoice.template_changed"
        debug_print('UserTemplateWidget.changed')
        choice = user_template_choice()
        self.setText(choice.current.name)
        self._refresh_action.setEnabled(not choice.current_is_default)
Beispiel #17
0
class Gui():
    """main gui class"""
    def __init__(self):
        self.mainwindow = QMainWindow()
        settings.get_settings()
        self.access = tuple(settings.access.items())
        self.progress = QProgressDialog("Setting up modules...", "cancel", 0,
                                        7, self.mainwindow)
        self.progress.setWindowTitle(
            QApplication.translate("MainWindow", str(settings.company), None,
                                   QApplication.UnicodeUTF8))

    def setup(self):
        """initializes the uio of the erp client"""
        self.progress.setFixedWidth(1000)
        self.progress.setCancelButton(None)
        # self.progress.setWindowModality(Qt.WindowModal)
        self.progress.setValue(1)
        self.mainwindow.setObjectName("MainWindow")
        self.mainwindow.resize(832, 668)
        self.mainwindow.setStyleSheet(
            "QToolBar{\n"
            "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n"
            "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n"
            "border: 0px;\n"
            "}\n"
            "QToolBar > QWidget{\n"
            "color:white;\n"
            "}\n"
            "QToolBar > QWidget:hover {\n"
            "background:transparent;\n"
            " }\n"
            "QToolBar > QWidget:checked {\n"
            "background:transparent;\n"
            " }\n"
            "#MainWindow{\n"
            "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n"
            "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n"
            "border: 0px;\n"
            "}\n"
            "")
        self.centralWidget = QWidget(self.mainwindow)
        self.centralWidget.setObjectName("centralWidget")
        self.gridLayout_2 = QGridLayout(self.centralWidget)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.stackedWidget = QStackedWidget(self.centralWidget)
        self.stackedWidget.setStyleSheet("")
        self.stackedWidget.setObjectName("stackedWidget")
        self.shortcut = NewShortcut()
        scroll = QScrollArea()
        scroll.setWidget(self.shortcut.shortcut_setting)
        self.stackedWidget.addWidget(self.shortcut.shortcut_setting)
        self.home_page = QWidget()
        self.home_page.setObjectName("home_page")
        self.gridLayout = QGridLayout(self.home_page)
        self.gridLayout.setObjectName("gridLayout")
        self.billing_frame_2 = QFrame(self.home_page)
        self.billing_frame_2.setStyleSheet(
            "background-image:url(:/images/billing_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#6CBED2;")
        self.billing_frame_2.setFrameShape(QFrame.StyledPanel)
        self.billing_frame_2.setFrameShadow(QFrame.Raised)
        self.billing_frame_2.setObjectName("billing_frame_2")
        self.verticalLayout_4 = QVBoxLayout(self.billing_frame_2)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        spacerItem = QSpacerItem(20, 217, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.verticalLayout_4.addItem(spacerItem)
        self.label_10 = QLabel(self.billing_frame_2)
        self.label_10.setStyleSheet("background:transparent;")
        self.label_10.setObjectName("label_10")
        self.verticalLayout_4.addWidget(self.label_10)
        self.gridLayout.addWidget(self.billing_frame_2, 0, 1, 1, 1)
        self.employee_frame_3 = QFrame(self.home_page)
        self.employee_frame_3.setStyleSheet(
            "background-image:url(:/images/employee_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#0099CC;")
        self.employee_frame_3.setFrameShape(QFrame.StyledPanel)
        self.employee_frame_3.setFrameShadow(QFrame.Raised)
        self.employee_frame_3.setObjectName("employee_frame_3")
        self.verticalLayout_5 = QVBoxLayout(self.employee_frame_3)
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        spacerItem1 = QSpacerItem(20, 217, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.verticalLayout_5.addItem(spacerItem1)
        self.label_11 = QLabel(self.employee_frame_3)
        self.label_11.setStyleSheet("background:transparent;")
        self.label_11.setObjectName("label_11")
        self.verticalLayout_5.addWidget(self.label_11)
        self.gridLayout.addWidget(self.employee_frame_3, 0, 2, 1, 1)
        self.menu_frame_4 = QFrame(self.home_page)
        self.menu_frame_4.setStyleSheet(
            "background-image:url(:/images/menu_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#297ACC;")
        self.menu_frame_4.setFrameShape(QFrame.StyledPanel)
        self.menu_frame_4.setFrameShadow(QFrame.Raised)
        self.menu_frame_4.setObjectName("menu_frame_4")
        self.verticalLayout_3 = QVBoxLayout(self.menu_frame_4)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        spacerItem2 = QSpacerItem(20, 216, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.verticalLayout_3.addItem(spacerItem2)
        self.label_12 = QLabel(self.menu_frame_4)
        self.label_12.setStyleSheet("background:transparent;")
        self.label_12.setObjectName("label_12")
        self.verticalLayout_3.addWidget(self.label_12)
        self.gridLayout.addWidget(self.menu_frame_4, 1, 0, 1, 1)
        self.report_frame_5 = QFrame(self.home_page)
        self.report_frame_5.setStyleSheet(
            "background-image:url(:/images/report_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#006BB2;")
        self.report_frame_5.setFrameShape(QFrame.StyledPanel)
        self.report_frame_5.setFrameShadow(QFrame.Raised)
        self.report_frame_5.setObjectName("report_frame_5")
        self.verticalLayout_6 = QVBoxLayout(self.report_frame_5)
        self.verticalLayout_6.setObjectName("verticalLayout_6")
        spacerItem3 = QSpacerItem(20, 216, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.verticalLayout_6.addItem(spacerItem3)
        self.label_13 = QLabel(self.report_frame_5)
        self.label_13.setStyleSheet("background:transparent;")
        self.label_13.setObjectName("label_13")
        self.verticalLayout_6.addWidget(self.label_13)
        self.gridLayout.addWidget(self.report_frame_5, 1, 1, 1, 1)
        self.waste_frame_6 = QFrame(self.home_page)
        self.waste_frame_6.setStyleSheet(
            "background-image:url(:/images/waste_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#003D7A;")
        self.waste_frame_6.setFrameShape(QFrame.StyledPanel)
        self.waste_frame_6.setFrameShadow(QFrame.Raised)
        self.waste_frame_6.setObjectName("waste_frame_6")
        self.verticalLayout_7 = QVBoxLayout(self.waste_frame_6)
        self.verticalLayout_7.setObjectName("verticalLayout_7")
        spacerItem4 = QSpacerItem(20, 216, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.verticalLayout_7.addItem(spacerItem4)
        self.label_14 = QLabel(self.waste_frame_6)
        self.label_14.setStyleSheet("background:transparent;")
        self.label_14.setObjectName("label_14")
        self.verticalLayout_7.addWidget(self.label_14)
        self.gridLayout.addWidget(self.waste_frame_6, 1, 2, 1, 1)
        self.inventory_frame_1 = QFrame(self.home_page)
        self.inventory_frame_1.setStyleSheet(
            "background-image:url(:/images/inventory_frame.png);\n"
            "background-repeat: no-repeat;\n"
            "background-position: center;\n"
            "background-color:#ADEBFF;")
        self.inventory_frame_1.setFrameShape(QFrame.StyledPanel)
        self.inventory_frame_1.setFrameShadow(QFrame.Raised)
        self.inventory_frame_1.setObjectName("inventory_frame_1")
        self.verticalLayout_2 = QVBoxLayout(self.inventory_frame_1)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        spacerItem5 = QSpacerItem(20, 217, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem5)
        self.label_9 = QLabel(self.inventory_frame_1)
        self.label_9.setStyleSheet("background:transparent;")
        self.label_9.setObjectName("label_9")
        self.verticalLayout_2.addWidget(self.label_9)
        self.gridLayout.addWidget(self.inventory_frame_1, 0, 0, 1, 1)
        self.stackedWidget.addWidget(self.home_page)
        self.detail_page = QWidget()
        self.detail_page.setObjectName("detail_page")
        self.horizontalLayout_2 = QHBoxLayout(self.detail_page)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.main_tabWidget = QTabWidget(self.detail_page)
        self.main_tabWidget.setAutoFillBackground(False)
        self.main_tabWidget.setStyleSheet("")
        self.main_tabWidget.setTabPosition(QTabWidget.West)
        self.main_tabWidget.setIconSize(QSize(60, 60))
        self.main_tabWidget.setElideMode(Qt.ElideNone)
        self.main_tabWidget.setObjectName("main_tabWidget")
        ##initializes the tabs
        self.add_tabs()
        self.main_tabWidget.setFocusPolicy(Qt.StrongFocus)
        self.main_tabWidget.focusInEvent = self.change_focus
        self.main_tabWidget.currentChanged.connect(self.change_focus)
        self.stackedWidget.currentChanged.connect(self.change_focus)
        ######
        self.horizontalLayout_2.addWidget(self.main_tabWidget)
        self.stackedWidget.addWidget(self.detail_page)
        if ('Admin', True) in self.access:
            self.stackedWidget.addWidget(Admin(self.mainwindow))
        notification = NotificationTab()
        tab = notification.notificationTab_tab_4
        tab.custom_class_object = notification  # class_object is used to access the api through the
        self.stackedWidget.addWidget(tab)
        self.gridLayout_2.addWidget(self.stackedWidget, 0, 0, 1, 1)
        self.mainwindow.setCentralWidget(self.centralWidget)
        self.menuBar = QMenuBar(self.mainwindow)
        self.menuBar.setGeometry(QRect(0, 0, 832, 29))
        self.menuBar.setObjectName("menuBar")
        self.mainwindow.setMenuBar(self.menuBar)
        self.mainToolBar = QToolBar(self.mainwindow)
        self.mainToolBar.setLayoutDirection(Qt.RightToLeft)
        self.mainToolBar.setStyleSheet("")
        self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.mainToolBar.setObjectName("mainToolBar")
        self.mainwindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar)
        self.statusBar = QStatusBar(self.mainwindow)
        self.statusBar.setObjectName("statusBar")
        self.mainwindow.setStatusBar(self.statusBar)
        self.toolBar = QToolBar(self.mainwindow)
        self.toolBar.setLayoutDirection(Qt.RightToLeft)
        self.toolBar.setStyleSheet("")
        self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.toolBar.setObjectName("toolBar")
        self.mainwindow.addToolBar(Qt.TopToolBarArea, self.toolBar)
        self.actionNotification = QAction(self.mainwindow)
        self.actionNotification.setCheckable(True)
        self.actionNotification.setChecked(False)
        self.actionNotification.setEnabled(True)
        icon6 = QIcon()
        icon6.addPixmap(QPixmap(":/images/notification.png"), QIcon.Normal,
                        QIcon.Off)
        self.actionNotification.setIcon(icon6)
        self.actionNotification.setAutoRepeat(True)
        self.actionNotification.setVisible(True)
        self.actionNotification.setIconVisibleInMenu(False)
        self.actionNotification.setObjectName("actionNotification")
        self.actionNotification
        self.actionAdmin = QAction(self.mainwindow)
        # self.actionAdmin.setCheckable(True)
        icon7 = QIcon()
        icon7.addPixmap(QPixmap(":/images/admin.png"), QIcon.Normal, QIcon.Off)
        self.actionAdmin.setIcon(icon7)
        self.actionAdmin.setObjectName("actionAdmin")
        self.actionRefresh = QAction(self.mainwindow)
        icon8 = QIcon()
        icon8.addPixmap(QPixmap(":/images/refresh.png"), QIcon.Normal,
                        QIcon.Off)
        self.actionRefresh.setIcon(icon8)
        self.actionRefresh.setObjectName("actionRefresh")
        self.actionHome = QAction(self.mainwindow)
        # self.actionHome.setCheckable(True)
        icon9 = QIcon()
        icon9.addPixmap(QPixmap(":/images/home.png"), QIcon.Normal, QIcon.Off)
        self.actionHome.setIcon(icon9)
        self.actionHome.setObjectName("actionHome")
        self.actionSettings = QAction(self.mainwindow)
        icon10 = QIcon()
        icon10.addPixmap(QPixmap(":/images/settings.png"), QIcon.Normal,
                         QIcon.Off)
        self.actionSettings.setIcon(icon10)
        self.actionSettings.setObjectName("actionRefresh")
        self.toolBar.addAction(self.actionNotification)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.actionAdmin)
        if ('Admin', True) in self.access:
            self.toolBar.addSeparator()
        else:
            self.actionAdmin.setVisible(False)
        self.toolBar.addAction(self.actionHome)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.actionRefresh)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.actionSettings)
        ##retranslates
        self.mainwindow.setWindowTitle(
            QApplication.translate("MainWindow", settings.company, None,
                                   QApplication.UnicodeUTF8))
        self.label_10.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">BILLING</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.label_11.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">EMPLOYEE</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.label_12.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">MENU</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.label_13.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">REPORT</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.label_14.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">WASTE</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.label_9.setText(
            QApplication.translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\">INVENTORY</p></body></html>",
                None, QApplication.UnicodeUTF8))
        self.inventory_frame_1.setToolTip(
            QApplication.translate("MainWindow", "Go to the Inventory Tab",
                                   None, QApplication.UnicodeUTF8))
        self.billing_frame_2.setToolTip(
            QApplication.translate("MainWindow", "Go to the Billing Tab", None,
                                   QApplication.UnicodeUTF8))
        self.employee_frame_3.setToolTip(
            QApplication.translate("MainWindow", "Go to the Employee Tab",
                                   None, QApplication.UnicodeUTF8))
        self.menu_frame_4.setToolTip(
            QApplication.translate("MainWindow", "Go to the Menu Tab", None,
                                   QApplication.UnicodeUTF8))
        self.report_frame_5.setToolTip(
            QApplication.translate("MainWindow", "Go to the Report Tab", None,
                                   QApplication.UnicodeUTF8))
        self.waste_frame_6.setToolTip(
            QApplication.translate("MainWindow", "Go to the Waste Tab", None,
                                   QApplication.UnicodeUTF8))
        self.toolBar.setWindowTitle(
            QApplication.translate("MainWindow", "toolBar", None,
                                   QApplication.UnicodeUTF8))
        self.actionNotification.setText("&&Notification")
        # QApplication.translate("MainWindow", "&Notification", None, QApplication.UnicodeUTF8))
        self.actionNotification.setToolTip(
            QApplication.translate("MainWindow",
                                   "Click to see new notifications", None,
                                   QApplication.UnicodeUTF8))
        # self.actionNotification.setShortcut(
        # QApplication.translate("MainWindow", "Ctrl+Shift+N", None, QApplication.UnicodeUTF8))
        self.actionAdmin.setText('&&Admin')
        # QApplication.translate("MainWindow", "Admin", None, QApplication.UnicodeUTF8))
        self.actionAdmin.setToolTip(
            QApplication.translate("MainWindow",
                                   "Click to go to admin interface", None,
                                   QApplication.UnicodeUTF8))
        # self.actionAdmin.setShortcut(
        # QApplication.translate("MainWindow", "Ctrl+Shift+A", None, QApplication.UnicodeUTF8))
        self.actionRefresh.setText("&&Refresh")
        # QApplication.translate("MainWindow", "Refresh", None, QApplication.UnicodeUTF8))
        self.actionRefresh.setToolTip(
            QApplication.translate("MainWindow",
                                   "refreshes the data from the server", None,
                                   QApplication.UnicodeUTF8))
        # self.actionRefresh.setShortcut(
        # QApplication.translate("MainWindow", "Ctrl+Shift+R", None, QApplication.UnicodeUTF8))
        self.actionHome.setText('&&Home')
        # QApplication.translate("MainWindow", "Home", None, QApplication.UnicodeUTF8))
        self.actionHome.setToolTip(
            QApplication.translate("MainWindow", "Go back to the home screen",
                                   None, QApplication.UnicodeUTF8))
        self.actionSettings.setText('&&Settings')
        # QApplication.translate("MainWindow", "Settings", None, QApplication.UnicodeUTF8))
        self.actionSettings.setToolTip(
            QApplication.translate("MainWindow", "Go to the settings panel",
                                   None, QApplication.UnicodeUTF8))
        # self.actionHome.setShortcut(
        #     QApplication.translate("MainWindow", "Ctrl+Shift+H", None, QApplication.UnicodeUTF8))
        self.stackedWidget.setCurrentIndex(1)
        self.main_tabWidget.setCurrentIndex(0)

        self.ob = self.main_tabWidget.tabBar()
        # self.add_tool_tip(self.ob) todo avoided due to segmentation fault error, left for future fixes
        self.tb = EventHandlerForTabBar()
        self.ob.installEventFilter(self.tb)

        QMetaObject.connectSlotsByName(self.mainwindow)

    def add_tabs(self):
        """
        adds new tabs
        """
        global logger
        if ('Inventory', True) in self.access:
            logger.info('initiating Inventory')
            icon = QIcon()
            icon.addPixmap(QPixmap(":/images/inventory.png"), QIcon.Normal,
                           QIcon.Off)
            from inventory.inventory import Inventory

            inventory = Inventory()
            # inventory.inventory_tab_1.setToolTip("Inventory Section")
            self.main_tabWidget.addTab(inventory.inventory_tab_1, icon, "")
            inventory.inventory_detail_tabWidget.setCurrentIndex(0)
        else:
            self.inventory_frame_1.setVisible(False)
        self.progress.setLabelText('Inventory Done....')
        self.progress.setValue(2)

        if ('Billing', True) in self.access:
            logger.info('initiating Billing')
            icon1 = QIcon()
            icon1.addPixmap(QPixmap(":/images/billing.png"), QIcon.Normal,
                            QIcon.Off)
            from billing.billing import Billing

            bill = Billing()
            # bill.billing_tab_2.setToolTip("Billing Section")
            self.main_tabWidget.addTab(bill.billing_tab_2, icon1, "")
            bill.billing_detail_tabWidget.setCurrentIndex(0)
        else:
            self.billing_frame_2.setVisible(False)
        self.progress.setLabelText('Billing Done...')
        self.progress.setValue(3)

        if ('Employee', True) in self.access:
            logger.info('initiating Employee')
            icon2 = QIcon()
            icon2.addPixmap(QPixmap(":/images/employee.png"), QIcon.Normal,
                            QIcon.Off)
            from employee.employee import Employee

            employee = Employee()
            # employee.employee_tab_3.setToolTip("Employee Section")
            self.main_tabWidget.addTab(employee.employee_tab_3, icon2, "")
            employee.employee_detail_tabWidget.setCurrentIndex(0)
        else:
            self.employee_frame_3.setVisible(False)
        self.progress.setLabelText('Employee Done...')
        self.progress.setValue(4)

        if ('Menu', True) in self.access:
            logger.info('initiating Menu')
            icon3 = QIcon()
            icon3.addPixmap(QPixmap(":/images/menu.png"), QIcon.Normal,
                            QIcon.Off)
            from menu.menu import Menu

            menu = Menu()
            # menu.menu_tab_4.setToolTip("Menu Section")
            self.main_tabWidget.addTab(menu.menu_tab_4, icon3, "")
            menu.menu_detail_tabWidget.setCurrentIndex(0)
        else:
            self.menu_frame_4.setVisible(False)
        self.progress.setLabelText('Menu Done....')
        self.progress.setValue(5)

        if ('Report', True) in self.access:
            logger.info('initiating Report')
            icon4 = QIcon()
            icon4.addPixmap(QPixmap(":/images/report.png"), QIcon.Normal,
                            QIcon.Off)
            from report.report import Report

            report = Report()
            # report.report_tab_5.setToolTip("Report Section")
            self.main_tabWidget.addTab(report.report_tab_5, icon4, "")
            report.report_detail_tabWidget.setCurrentIndex(0)
        else:
            self.report_frame_5.setVisible(False)
        self.progress.setLabelText('Report Done....')
        self.progress.setValue(6)

        if ('Waste', True) in self.access:
            logger.info('initiating Waste')
            icon5 = QIcon()
            icon5.addPixmap(QPixmap(":/images/waste.png"), QIcon.Normal,
                            QIcon.Off)
            from waste.waste import Waste

            waste = Waste()
            # waste.waste_tab_6.setToolTip("Waste Section")
            self.main_tabWidget.addTab(waste.waste_tab_6, icon5, "")
            waste.waste_detail_tabWidget.setCurrentIndex(0)
        else:
            self.waste_frame_6.setVisible(False)
        self.progress.setLabelText('Waste Done....')
        self.progress.setValue(7)

    def change_focus(self, event=None):
        """
        focus method to set focus to a tab to initialize the corresponding events of the tab
        """
        wid = self.main_tabWidget.currentWidget()
        if wid:
            if wid.isVisible():
                # print wid.objectName()
                # print '1y'
                wid.setFocus()

    def add_tool_tip(
        self, ob
    ):  # todo not working causing segmentation fault, avoided calling this function
        """
        method to add tool tip to the tabs
        :param ob: Tab bar
        """
        obj = ob
        count = obj.count()
        hardcode = {
            0: 'Inventory Section',
            1: "Billing Section",
            2: "Employee Section",
            3: "Menu Section",
            4: "Report Section",
            5: "Waste Section"
        }
        for i in range(count):
            obj.setTabToolTip(i, hardcode[i])
Beispiel #18
0
class DeliverySlipPanel(HorsePanel):

    delivery_slip_changed = Signal()

    def close_panel(self):
        self.filter_widget.remember_current_selection( configuration)

    def _selected_slip(self):
        cur_ndx = self.search_results_view.currentIndex()
        if cur_ndx.row() >= 0:
            return cur_ndx.model().object_at(cur_ndx.row())
        return None

    def reprint(self):
        cur_ndx = self.search_results_view.currentIndex()
        slip_id = cur_ndx.model().index(cur_ndx.row(),0).data()

        if dao.delivery_slip_part_dao.id_exists(slip_id):
            print_delivery_slip(dao,slip_id)
        else:
            makeErrorBox(_("The delivery slip {} doesn't exist").format(slip_id)).exec_()

    def desactivate(self):
        slip_id = self._selected_slip().delivery_slip_id
        mainlog.debug("Desactivate slip {}".format(slip_id))
        dao.delivery_slip_part_dao.deactivate(slip_id)
        self.refresh(slip_id)
        self.delivery_slip_changed.emit()

    def activate(self):
        slip_id = self._selected_slip().delivery_slip_id
        dao.delivery_slip_part_dao.activate(slip_id)
        self.refresh(slip_id)
        self.delivery_slip_changed.emit()

    def delete(self):
        slip_id = self._selected_slip().delivery_slip_id
        dao.delivery_slip_part_dao.delete_last(slip_id)
        self.refresh(slip_id)
        self.delivery_slip_changed.emit()

    @Slot()
    def show_actions(self):
        button = self.action_menu.parent()
        p = button.mapToGlobal(QPoint(0,button.height()))
        self.action_menu.exec_(p)

    @Slot()
    def _toggle_edit_filters(self):
        self.filter_widget.setVisible( not self.filter_widget.isVisible())

    def __init__(self,parent):
        super(DeliverySlipPanel,self).__init__(parent)

        title = _("Delivery slips")

        self.slip_data = None

        self.set_panel_title(_("Delivery slip overview"))
        self.reprint_delivery_slip = QAction(_("Reprint delivery slip"),self) # , parent
        self.reprint_delivery_slip.triggered.connect( self.reprint)
        # self.reprint_delivery_slip.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_V))
        self.reprint_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        # self.controller_operation.view.addAction(self.reprint_delivery_slip)


        self.desactivate_delivery_slip = QAction(_("Desactivate delivery slip"),self) # , parent
        self.desactivate_delivery_slip.triggered.connect( self.desactivate)
        self.desactivate_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut)

        self.activate_delivery_slip = QAction(_("Activate delivery slip"),self) # , parent
        self.activate_delivery_slip.triggered.connect( self.activate)
        self.activate_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut)

        self.delete_delivery_slip = QAction(_("Delete delivery slip"),self) # , parent
        self.delete_delivery_slip.triggered.connect( self.delete)
        self.delete_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut)


        filter_family = FilterQuery.DELIVERY_SLIPS_FAMILY
        self.filter_widget = PersistentFilter( filter_family, suggestion_finder)
        self.filter_widget.apply_filter.connect(self.apply_filter_slot)
        self.filter_widget.hide()

        navigation = NavBar( self,
                             [ (self.filter_widget.get_filters_combo(), None),
                               (_("Edit filter"),self._toggle_edit_filters),
                               (_("Action"),self.show_actions) ] )

        self.title_widget = TitleWidget(title, self, navigation) # navigation)


        self.action_menu = QMenu(navigation.buttons[0])
        list_actions = [ (self.reprint_delivery_slip,None),
                         (self.activate_delivery_slip,None),
                         (self.desactivate_delivery_slip,None),
                         # (self.delete_delivery_slip,None)
        ]
        populate_menu(self.action_menu, self, list_actions, context=Qt.WidgetWithChildrenShortcut)

        # self.setWindowTitle(title)


        top_layout = QVBoxLayout(self)

        # self.filter_line_edit = QLineEdit()

        # self.filter_line_edit = QueryLineEdit(suggestion_finder)
        initialize_customer_cache() # FIXME Not the place to do that

        # filter_family = 'delivery_slips'
        # self.filter_name = FiltersCombo(self, filter_family)
        # filter_widget = PersistentFilter(filter_family, self.filter_name)
        # filter_widget.apply_filter.connect(self.apply_filter_slot)

        self.proto = []
        self.proto.append( IntegerNumberPrototype('delivery_slip_id',_("Slip Nr"), editable=False))
        self.proto.append( DatePrototype('creation',_('Date'), editable=False))
        self.proto.append( TextLinePrototype('fullname',_('Customer'), editable=False))
        self.proto.append( TextLinePrototype('user_label',_('Order'), editable=False))

        self.search_results_model = DeliverySlipPanelModel(self.proto, self)
        self.search_results_view = PrototypedQuickView(self.proto, self)
        self.search_results_view.setModel(self.search_results_model)


        self.search_results_view.verticalHeader().hide()
        self.search_results_view.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents)
        self.search_results_view.horizontalHeader().setResizeMode(2, QHeaderView.Stretch)
        self.search_results_view.horizontalHeader().setSortIndicatorShown(True)
        self.search_results_view.horizontalHeader().setSortIndicator(0,Qt.AscendingOrder)
        self.search_results_view.horizontalHeader().sectionClicked.connect(self._section_clicked)
        self.search_results_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.search_results_view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.search_results_view.selectionModel().currentRowChanged.connect(self.row_selected)

        self.slip_part_view = DeliverySlipViewWidget(self)

        hlayout_results = QHBoxLayout()
        # w = SubFrame(_("Delivery slips"),self.search_results_view,None)
        hlayout_results.addWidget(self.search_results_view)
        w = SubFrame(_("Detail"),self.slip_part_view,None)
        hlayout_results.addWidget(w)

        top_layout.addWidget(self.title_widget)
        top_layout.addWidget(self.filter_widget)
        top_layout.addLayout(hlayout_results)
        top_layout.setStretch(2,100)
        self.setLayout(top_layout)

        self.filter_widget.load_last_filter( configuration)



    def refresh(self,slip_id):
        filter_string = self.filter_line_edit.text()
        self.apply_filter_slot(filter_string)

        if slip_id:
            ndx = self.search_results_model.find_index( lambda s:s.delivery_slip_id == slip_id)

            r = 0
            m = self.search_results_model
            if ndx:
                r = ndx.row()

            s = QItemSelection(m.index(r,0), m.index(r, m.columnCount()-1))
            self.search_results_view.selectionModel().select(s, QItemSelectionModel.Select)

    @Slot(int)
    def _section_clicked(self,logical_ndx):
        self.refresh_action()

    @Slot(str)
    def apply_filter_slot(self, filter_string):
        if filter_string:
            try:
                self.slip_data = dao.delivery_slip_part_dao.load_slip_parts_on_filter(filter_string)
            except DataException as de:
                if de.code == DataException.CRITERIA_IS_EMPTY:
                    showErrorBox(_("Error in the filter !"),_("The filter can't be empty"),object_name="filter_is_empty")
                elif de.code == DataException.CRITERIA_IS_TOO_SHORT:
                    showErrorBox(_("Error in the filter !"),_("The filter is too short"),object_name="filter_is_too_short")
                elif de.code == DataException.CRITERIA_IS_TOO_LONG:
                    showErrorBox(_("Error in the filter !"),_("The filter is too long"),object_name="filter_is_too_long")
                return
        else:
            self.slip_data = dao.delivery_slip_part_dao.find_recent2(1000)
        self.refresh_action()


    def refresh_action(self):

        if self.slip_data == None:
            self.slip_data = dao.delivery_slip_part_dao.find_recent2(1000)

        data = self.slip_data
        headers = self.search_results_view.horizontalHeader()
        section_sorted = headers.sortIndicatorSection()
        sort_criteria = self._get_sort_criteria( section_sorted)
        sort_order = None

        if sort_criteria:
            sort_order = headers.sortIndicatorOrder()
            data = sorted(data, key=cmp_to_key(sort_criteria), reverse = sort_order == Qt.DescendingOrder)

        self.search_results_model.buildModelFromObjects(data)

        if sort_criteria:
            # Changing the model removes the sort order (which makes sense because
            # changing the model may alter the order of rows)
            headers.setSortIndicator(section_sorted,sort_order)

        self.search_results_view.setFocus(Qt.OtherFocusReason)


    @Slot(QModelIndex,QModelIndex)
    def row_selected(self,cur_ndx,prev_ndx):
        if cur_ndx.model():
            slip = cur_ndx.model().object_at( cur_ndx.row())
            if slip:
                slip_id = slip.delivery_slip_id
                self.slip_part_view.set_delivery_slip_parts(dao.delivery_slip_part_dao.load_slip_parts_frozen(slip_id))

                self.activate_delivery_slip.setEnabled( not slip.active)
                self.desactivate_delivery_slip.setEnabled( slip.active)
                self.delete_delivery_slip.setEnabled( cur_ndx.row() == 0)
                return

        self.slip_part_view.set_delivery_slip_parts(None)

    SECTION_SLIP_ID = 0
    SECTION_CREATION_DATE = 1
    SECTION_CUSTOMER = 2
    SECTION_ORDER_LABEL = 3


    def _get_sort_criteria(self,section_sorted):
        sort_criteria = None

        # True if the parts of the order stay grouped
        # together in the table
        order_stay_together = True

        if section_sorted == self.SECTION_CUSTOMER: # Customer
            sort_criteria = lambda a,b: cmp(a.fullname, b.fullname) or \
                            cmp(a.delivery_slip_id,b.delivery_slip_id)
        elif section_sorted == self.SECTION_CREATION_DATE:
            sort_criteria = lambda a,b: cmp(a.creation or date(2100,1,1), b.creation or date(2100,1,1))
        elif section_sorted == self.SECTION_SLIP_ID:
            sort_criteria = lambda a,b: cmp(a.delivery_slip_id, b.delivery_slip_id)
        elif section_sorted == self.SECTION_ORDER_LABEL:
            sort_criteria = lambda a,b: cmp(a.user_label, b.user_label)
        else:
            sort_criteria = None

        if sort_criteria is not None:
            self.current_sort_criteria = sort_criteria
        else:
            sort_criteria = self.current_sort_criteria

        return sort_criteria
    def contextMenuEvent(self, event):
        """
        Handles the ``contextMenuEvent`` event for :class:`StatusBarButton`.

        :param `event`: a `QContextMenuEvent` event to be processed.
        """
        QApplication.setOverrideCursor(Qt.ArrowCursor)
        menu = QMenu(self)
        objName = self.objectName()
        themeDir = gIconDir + os.sep + '..' + os.sep + self.mainWin.getSettingsGeneralIconTheme() + os.sep
        s = "&Settings..."
        if objName == "StatusBarButtonSNAP":

            settingsSnapAction = QAction(QIcon(themeDir + "gridsnapsettings.png"), s, menu)
            settingsSnapAction.triggered.connect(self.settingsSnap)
            menu.addAction(settingsSnapAction)

        elif objName == "StatusBarButtonGRID":

            settingsGridAction = QAction(QIcon(themeDir + "gridsettings.png"), s, menu)
            settingsGridAction.triggered.connect(self.settingsGrid)
            menu.addAction(settingsGridAction)

        elif objName == "StatusBarButtonRULER":

            settingsRulerAction = QAction(QIcon(themeDir + "rulersettings.png"), s, menu)
            settingsRulerAction.triggered.connect(self.settingsRuler)
            menu.addAction(settingsRulerAction)

        elif objName == "StatusBarButtonORTHO":

            settingsOrthoAction = QAction(QIcon(themeDir + "orthosettings.png"), s, menu)
            settingsOrthoAction.triggered.connect(self.settingsOrtho)
            menu.addAction(settingsOrthoAction)

        elif objName == "StatusBarButtonPOLAR":

            settingsPolarAction = QAction(QIcon(themeDir + "polarsettings.png"), s, menu)
            settingsPolarAction.triggered.connect(self.settingsPolar)
            menu.addAction(settingsPolarAction)

        elif objName == "StatusBarButtonQSNAP":

            settingsQSnapAction = QAction(QIcon(themeDir + "qsnapsettings.png"), s, menu)
            settingsQSnapAction.triggered.connect(self.settingsQSnap)
            menu.addAction(settingsQSnapAction)

        elif objName == "StatusBarButtonQTRACK":

            settingsQTrackAction = QAction(QIcon(themeDir + "qtracksettings.png"), s, menu)
            settingsQTrackAction.triggered.connect(self.settingsQTrack)
            menu.addAction(settingsQTrackAction)

        elif objName == "StatusBarButtonLWT":

            gview = self.mainWin.activeView()
            if gview:

                enableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender On", menu)
                enableRealAction.setEnabled(not gview.isRealEnabled())
                enableRealAction.triggered.connect(self.enableReal)
                menu.addAction(enableRealAction)

                disableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender Off", menu)
                disableRealAction.setEnabled(gview.isRealEnabled())
                disableRealAction.triggered.connect(self.disableReal)
                menu.addAction(disableRealAction)

            settingsLwtAction = QAction(QIcon(themeDir + "lineweightsettings" + ".png"), s, menu)
            settingsLwtAction.triggered.connect(self.settingsLwt)
            menu.addAction(settingsLwtAction)

        menu.exec_(event.globalPos())
        QApplication.restoreOverrideCursor()
        self.statusbar.clearMessage()
    def handleEvents(self, event, signals):
        att = self.axisOrder[self.findAxisIndex(event.x)]
        # context menu
        if event.contextRequested:
            contextMenu = QMenu(self)
            
            contextMenu.addAction(u'Select all')
            contextMenu.addAction(u'Select none')
            
            contextMenu.addSeparator()
            
            
            act = QAction(u'Hide Axis', self)
            contextMenu.addAction(act)
            if len(self.axisOrder) <= 1:
                act.setEnabled(False)
            
            axesMenu = QMenu(u'Show/Hide Axes', self)
            axesActions = QActionGroup(self)
            for a in self.axisOrder:
                act = QAction(a,self,checkable=True)
                if self.axes[a].visible:
                    act.toggle()
                if len(self.axisOrder) <= 1:
                    act.setEnabled(False)
                axesActions.addAction(act)
            for act in axesActions.actions():
                axesMenu.addAction(act)
            contextMenu.addMenu(axesMenu)
            
            contextMenu.addSeparator()
            
            contextMenu.addAction(u'Use as X axis')
            contextMenu.addAction(u'Use as Y axis')
            
            resultAction = contextMenu.exec_(QCursor.pos())
            
            if resultAction != None and resultAction != 0:
                # Select all
                if resultAction.text() == u'Select all':
                    self.app.intMan.newOperation(operation.ALL,att=att.dataAxis)
                
                # Select none
                if resultAction.text() == u'Select none':
                    self.app.intMan.newOperation(operation.NONE,att=att.dataAxis)
                
                # Hide axis
                if resultAction.text() == u'Hide Axis':
                    self.toggleVisible(att)
                
                # Toggle axis
                if resultAction.actionGroup() == axesActions:
                    self.toggleVisible(resultAction.text())

                # X axis
                if resultAction.text() == u'Use as X axis':
                    if self.app.currentYattribute != self.app.currentXattribute:
                        self.axes[self.app.currentXattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor)
                        self.axes[self.app.currentXattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor
                    self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor)
                    self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor
                    
                    self.app.notifyAxisChange(att,xAxis=True)
                
                # Y axis
                if resultAction.text() == u'Use as Y axis':
                    if self.app.currentXattribute != self.app.currentYattribute:
                        self.axes[self.app.currentYattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor)
                        self.axes[self.app.currentYattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor
                    self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor)
                    self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor
                    
                    self.app.notifyAxisChange(att,xAxis=False)
        
        #if linesMoved:
        #    self.highlightedLayer.refreshLines(self.app.highlightedRsNumbers)
        
        return signals
 def _get_menu_header(self, title):
     header = QAction(title, self)
     header.setEnabled(False)
     return header
Beispiel #22
0
class AppWindow(QMainWindow):

    # =====================
    # The Main Window Class
    # =====================

    def __init__(self):
        # ====================
        # Constructor Function
        # ====================

        QMainWindow.__init__(self)
        self.setWindowTitle("Virtua Text Editor")
        self.setGeometry(300, 300, 1024, 768)

        QToolTip.setFont(QFont("Ubuntu", 10, QFont.Normal))
        self.setToolTip('Application Window')

        # ================================
        # Function to setup menus, etc etc
        # ================================
        self.textEdit = QTextEdit()
        self.textEdit.setFont(QFont("Ubuntu", 12, QFont.Normal))
        self.setCentralWidget(self.textEdit)
        self.create_menus()
        self.create_actions()

        self.fileMenu.addAction(self.newAction)
        self.fileMenu.addAction(self.openAction)
        self.fileMenu.addAction(self.saveAction)
        self.fileMenu.addAction(self.saveasAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.printAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAction)

        self.editMenu.addAction(self.undoAction)
        self.editMenu.addAction(self.redoAction)
        self.editMenu.addAction(self.cutAction)
        self.editMenu.addAction(self.copyAction)
        self.editMenu.addAction(self.pasteAction)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.selectallAction)
        self.editMenu.addAction(self.deselectallAction)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.findAction)
        self.editMenu.addAction(self.findReplaceAction)

        self.helpMenu.addAction(self.aboutAction)

        self.app_status_bar = QStatusBar()
        self.app_status_bar.showMessage('Ready, v0.2', 10000)
        self.setStatusBar(self.app_status_bar)

        self.create_toolbar()
        self.toolbar.addAction(self.newAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.cutAction)
        self.toolbar.addAction(self.copyAction)
        self.toolbar.addAction(self.pasteAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.printAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.undoAction)
        self.toolbar.addAction(self.redoAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.findAction)
        self.toolbar.addAction(self.findReplaceAction)


    def create_toolbar(self):
        # ===============================
        # Function to create the toolbar.
        # ===============================
        self.toolbar = self.addToolBar('Main')
        self.toolbar.setToolButtonStyle(PySide.QtCore.Qt.ToolButtonTextUnderIcon)

    def newfile(self):
        self.textEdit.setText('')

    # TODO: Create the file/open method
    def openfile(self):
        print "Open File Menu Selected"

    # TODO: Create the file/save method
    def savefile(self):
        print "Save File Menu Selected"

    # TODO: Create the file/saveas method
    def saveasfile(self):
        print "Save As File Menu Selected"

    # TODO: Create the print method
    def print_page(self):
        print "Print Page Selected"

    # TODO: Create the find method
    def find_text(self):
        print "Find text option selected"

    # TODO: Create the replace method
    def find_replace_text(self):
        print "Replace text selected"

    def create_actions(self):
        # =========================================
        # Function to create actions for menu items
        # =========================================

        self.newAction = QAction(QIcon('digital_assets/document-new.svg'), 'New', self)
        self.newAction.setShortcut(QKeySequence.New)
        self.newAction.setStatusTip("Create a New File")
        self.newAction.setIconText("New")
        self.newAction.triggered.connect(self.newfile)

        self.openAction = QAction(QIcon('digital_assets/document-open.svg'), 'Open', self)
        self.openAction.setShortcut(QKeySequence.Open)
        self.openAction.setStatusTip("Open a file")
        self.openAction.triggered.connect(self.openfile)

        self.saveAction = QAction(QIcon('digital_assets/document-save.svg'), 'Save', self)
        self.saveAction.setShortcut(QKeySequence.Save)
        self.saveAction.setStatusTip("Save a file")
        self.saveAction.triggered.connect(self.savefile)

        self.saveasAction = QAction(QIcon('digital_assets/document-save-as.svg'), 'Save As', self)
        self.saveasAction.setShortcut(QKeySequence.SaveAs)
        self.saveasAction.setStatusTip("Save a File As....")
        self.saveasAction.triggered.connect(self.saveasfile)

        self.printAction = QAction(QIcon('digital_assets/document-print.svg'), 'Print', self)
        self.printAction.setShortcut(QKeySequence.Print)
        self.printAction.setStatusTip("Print")
        self.printAction.triggered.connect(self.print_page)

        self.exitAction = QAction(QIcon('digital_assets/application-exit.svg'), 'Exit', self)
        self.exitAction.setShortcut(QKeySequence.Quit)
        self.exitAction.setStatusTip("Exit the Application")
        self.exitAction.triggered.connect(self.quit_application)

        self.undoAction = QAction(QIcon('digital_assets/undo.svg'), 'Undo', self)
        self.undoAction.setShortcut(QKeySequence.Undo)
        self.undoAction.setStatusTip("Undo")
        self.undoAction.triggered.connect(self.textEdit.undo)

        self.redoAction = QAction(QIcon('digital_assets/redo.svg'), 'Redo', self)
        self.redoAction.setShortcut(QKeySequence.Redo)
        self.redoAction.setStatusTip("Redo")
        self.redoAction.triggered.connect(self.textEdit.redo)

        self.cutAction = QAction(QIcon('digital_assets/edit-cut.svg'), 'Cut', self)
        self.cutAction.setShortcut(QKeySequence.Cut)
        self.cutAction.setStatusTip("Cut")
        self.cutAction.setEnabled(False)
        self.cutAction.triggered.connect(self.textEdit.cut)

        self.copyAction = QAction(QIcon('digital_assets/edit-copy.svg'), 'Copy', self)
        self.copyAction.setShortcut(QKeySequence.Copy)
        self.copyAction.setStatusTip("Copy")
        self.copyAction.setEnabled(False)
        self.copyAction.triggered.connect(self.textEdit.copy)

        self.pasteAction = QAction(QIcon('digital_assets/edit-paste.svg'), 'Paste', self)
        self.pasteAction.setShortcut(QKeySequence.Paste)
        self.pasteAction.setStatusTip("Paste")
        self.pasteAction.setEnabled(False)
        self.pasteAction.triggered.connect(self.textEdit.paste)

        self.selectallAction = QAction(QIcon('digital_assets/edit-select-all.svg'), 'Select All', self)
        self.selectallAction.setShortcut(QKeySequence.SelectAll)
        self.selectallAction.setStatusTip("Select All")
        self.selectallAction.triggered.connect(self.textEdit.selectAll)

        self.deselectallAction = QAction(QIcon('digital_assets/edit-select-all.svg'), 'Deselect All', self)
        self.deselectallAction.setShortcut("Shift+Ctrl+A")
        self.deselectallAction.setStatusTip("Deselect All")
        self.deselectallAction.triggered.connect(self.deselect_all_text)

        self.findAction = QAction(QIcon('digital_assets/edit-find.svg'), 'Find', self)
        self.findAction.setShortcut(QKeySequence.Find)
        self.findAction.setStatusTip("Find")
        self.findAction.triggered.connect(self.find_text)

        self.findReplaceAction = QAction(QIcon('digital_assets/edit-find-replace.svg'), 'Replace', self)
        self.findReplaceAction.setShortcut(QKeySequence.Replace)
        self.findReplaceAction.setShortcut("Replace")
        self.findReplaceAction.triggered.connect(self.find_replace_text)

        self.aboutAction = QAction(QIcon('digital_assets/AppIcon.png'), 'About', self)
        self.aboutAction.setStatusTip("Displays info about the application")
        self.aboutAction.triggered.connect(self.show_about)


    def deselect_all_text(self):
        text_cursor = self.textEdit.textCursor()
        text_cursor.clearSelection()
        self.textEdit.setTextCursor(text_cursor)

    def create_menus(self):
        # ================================
        # Function to create the menu bar.
        # ================================
        self.fileMenu = self.menuBar().addMenu("File")
        self.fileMenu.setFont(QFont("Ubuntu", 10, QFont.Normal))
        self.editMenu = self.menuBar().addMenu("Edit")
        self.editMenu.setFont(QFont("Ubuntu", 10, QFont.Normal))
        self.helpMenu = self.menuBar().addMenu("Help")
        self.helpMenu.setFont(QFont("Ubuntu", 10, QFont.Normal))

    def set_icon(self):
        # ===============================
        # Function to set the Window Icon
        # ===============================
        appicon = QIcon('digital_assets/AppIcon.png')
        self.setWindowIcon(appicon)

    def quit_application(self):
        # ================================
        # Function to quit the application
        # ================================
        userinfo = QMessageBox.question(self, "Confirmation", "This will quit, Do you want to continue?",
                                        QMessageBox.Yes | QMessageBox.No)
        if userinfo == QMessageBox.Yes:
            templateApp.quit()
        if userinfo == QMessageBox.No:
            pass

    def show_about(self):
        QMessageBox.about(self, "About Virtua Text Editor",
                          "<b><h3>Virtua Text Editor</h3></b>"
                          "<p><h4>Virtua Text Editor has been written to serve as a template"
                          " that can be used as a basis for creating a working application."
                          " All of the components that make up the core functions of an"
                          " application, the main window, a status bar, menus and dialogs"
                          " are provided here as a basis for writing something new and interesting</h4></p>")

    def center_application(self):
        # ============================================
        # Function to center the Application on screen
        # ============================================
        qrect = self.frameGeometry()
        centerpoint = QDesktopWidget().availableGeometry().center()
        qrect.moveCenter(centerpoint)
        self.move(qrect.topLeft())
def createAction(self, icon, toolTip, statusTip, scripted=False):
    """
    TOWRITE

    :param `icon`: TOWRITE
    :type `icon`: QString
    :param `toolTip`: TOWRITE
    :type `toolTip`: QString
    :param `statusTip`: TOWRITE
    :type `statusTip`: QString
    :param `scripted`: TOWRITE
    :type `scripted`: bool
    :rtype: `QAction`_

    .. TODO:: send the global Icon, Image, Commands Dirs in to be used.

    """
    connect = self.connect  # NOT local optimization, but for ease of the code looking similar to the C++ whash
    mdiArea = self.mdiArea  # ditto

    ACTION = QAction(
        QIcon(self.gIconDir + os.sep + self.getSettingsGeneralIconTheme() + "/" + icon + ".png"), toolTip, self
    )  # QAction *  # TODO: Qt4.7 wont load icons without an extension...
    ACTION.setStatusTip(statusTip)
    ACTION.setObjectName(icon)
    # TODO: Set What's This Context Help to statusTip for now so there is some infos there.
    # Make custom whats this context help popup with more descriptive help than just
    # the status bar/tip one liner(short but not real long) with a hyperlink in the custom popup
    # at the bottom to open full help file description. Ex: like wxPython AGW's SuperToolTip.
    ACTION.setWhatsThis(statusTip)
    # TODO: Finish All Commands ... <.<

    if icon == "donothing":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("doNothing()"))
    elif icon == "new":
        ACTION.setShortcut(QKeySequence.New)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("newFile()"))
    elif icon == "open":
        ACTION.setShortcut(QKeySequence.Open)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("openFile()"))
    elif icon == "save":
        ACTION.setShortcut(QKeySequence.Save)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("savefile()"))
    elif icon == "saveas":
        ACTION.setShortcut(QKeySequence.SaveAs)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("saveasfile()"))
    elif icon == "print":
        ACTION.setShortcut(QKeySequence.Print)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("print_()"))
    elif icon == "designdetails":
        ACTION.setShortcut(QKeySequence("Ctrl+D"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("designDetails()"))
    elif icon == "exit":
        ACTION.setShortcut(QKeySequence("Ctrl+Q"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("exit()"))

    elif icon == "cut":
        ACTION.setShortcut(QKeySequence.Cut)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("cut()"))
    elif icon == "copy":
        ACTION.setShortcut(QKeySequence.Copy)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("copy()"))
    elif icon == "paste":
        ACTION.setShortcut(QKeySequence.Paste)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("paste()"))

    elif icon == "windowcascade":
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("cascade()"))
    elif icon == "windowtile":
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("tile()"))
    elif icon == "windowclose":
        ACTION.setShortcut(QKeySequence.Close)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("onCloseWindow()"))
    elif icon == "windowcloseall":
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("closeAllSubWindows()"))
    elif icon == "windownext":
        ACTION.setShortcut(QKeySequence.NextChild)
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activateNextSubWindow()"))
    elif icon == "windowprevious":
        ACTION.setShortcut(QKeySequence.PreviousChild)
        connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activatePreviousSubWindow()"))

    elif icon == "help":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("help()"))
    elif icon == "changelog":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("changelog()"))
    elif icon == "tipoftheday":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("tipOfTheDay()"))
    elif icon == "about":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("about()"))
    elif icon == "whatsthis":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("whatsThisContextHelp()"))

    elif icon == "icon16":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon16()"))
    elif icon == "icon24":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon24()"))
    elif icon == "icon32":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon32()"))
    elif icon == "icon48":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon48()"))
    elif icon == "icon64":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon64()"))
    elif icon == "icon128":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon128()"))

    elif icon == "settingsdialog":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("settingsDialog()"))

    elif icon == "undo":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("undo()"))
    elif icon == "redo":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("redo()"))

    elif icon == "makelayercurrent":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("makeLayerActive()"))
    elif icon == "layers":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerManager()"))
    elif icon == "layerprevious":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerPrevious()"))

    elif icon == "textbold":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextBold(bool)"))
    elif icon == "textitalic":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextItalic(bool)"))
    elif icon == "textunderline":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextUnderline(bool)"))
    elif icon == "textstrikeout":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextStrikeOut(bool)"))
    elif icon == "textoverline":
        ACTION.setCheckable(True)
        connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextOverline(bool)"))

    elif icon == "zoomrealtime":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomRealtime()"))
    elif icon == "zoomprevious":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomPrevious()"))
    elif icon == "zoomwindow":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomWindow()"))
    elif icon == "zoomdynamic":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomDynamic()"))
    elif icon == "zoomscale":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomScale()"))
    elif icon == "zoomcenter":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomCenter()"))
    elif icon == "zoomin":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomIn()"))
    elif icon == "zoomout":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomOut()"))
    elif icon == "zoomselected":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomSelected()"))
    elif icon == "zoomall":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomAll()"))
    elif icon == "zoomextents":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomExtents()"))

    elif icon == "panrealtime":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panrealtime()"))
    elif icon == "panpoint":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panpoint()"))
    elif icon == "panleft":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panLeft()"))
    elif icon == "panright":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panRight()"))
    elif icon == "panup":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panUp()"))
    elif icon == "pandown":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("panDown()"))

    elif icon == "day":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("dayVision()"))
    elif icon == "night":
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("nightVision()"))

    elif scripted:
        ACTION.setIcon(QIcon(self.gAppDir + os.sep + "commands/" + icon + "/" + icon + ".png"))
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("runCommand()"))

    else:
        ACTION.setEnabled(False)
        connect(ACTION, SIGNAL("triggered()"), self, SLOT("stub_implement()"))

    return ACTION