예제 #1
0
class ViewSourceDialogTabber(QMainWindow):
    def __init__(self, parent=None, title="Source"):
        super(ViewSourceDialogTabber, self).__init__(parent)
        self.setWindowTitle(title)
        self.tabs = QTabWidget(self)
        self.tabs.setElideMode(Qt.ElideRight)
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.removeTab)
        self.setCentralWidget(self.tabs)
        self.tabs.currentChanged.connect(self.updateWindowTitle)
    def sizeHint(self):
        return QSize(640, 480)
    def removeTab(self):
        self.tabs.removeTab(self.tabs.currentIndex())
    def addTab(self, title="New Tab", data=""):
        vsd = ViewSourceDialog(self, str(title))
        vsd.setPlainText(data)
        self.tabs.addTab(vsd, tr("Source of %s") % (title,))
        self.tabs.setCurrentIndex(self.tabs.count()-1)
        self.raise_()
        self.activateWindow()
    def updateWindowTitle(self):
        try: self.setWindowTitle(tr("Source of %s") % (self.tabs.currentWidget().windowTitle(),))
        except: pass
        if self.tabs.count() == 0:
            self.hide()
예제 #2
0
class MyPlugin(Plugin):
    def __init__(self, context):
        super(MyPlugin, self).__init__(context)
        self.setObjectName("main_window")
        self._widget = QWidget()
        self._widget.setMinimumSize(1280, 800)
        self._widget.setWindowTitle("Yonah RQt")
        context.add_widget(self._widget)

        # Get path to UI file and load it
        ui_file = os.path.join(rospkg.RosPack().get_path("yonah_rqt"),
                               "resource", "second_window.ui")
        loadUi(ui_file, self._widget)

        # Show _widget.windowTitle on left-top of each plugin (when it's set in _widget). This is useful when you open multiple
        # plugins at once. Also if you open multiple instances of your plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number():
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (" (%d)" % context.serial_number()))

        # Declare attributes
        self.saved = ""
        self.time = 0
        self.proper_shutdown = 0
        self.destination_id = 1
        self.aircraft_list = []
        self.aircrafts_info = {}
        self.checklist_info = {}
        self.aircrafts_flight_data = {}

        # Declare attributes for each imported class
        self.PopupMessages = PopupMessages()
        self.WaypointWindow = WaypointWindow(self.aircraft_list)
        self.SummaryWindow = SummaryWindow(self.aircraft_list)
        self.CommandWindow = CommandWindow(self.aircraft_list, self.tab_change)

        self.CommandWindow.change_valid_ids()
        self.create_layout()
        self.shortcuts()

        # Subscriber lists
        rospy.Subscriber("ogc/from_despatcher/regular", RegularPayload,
                         self.regular_payload)
        rospy.Subscriber("ogc/yonahtext", String, self.status_text)
        rospy.Subscriber("ogc/from_despatcher/ondemand", String, self.ondemand)
        rospy.Subscriber("ogc/files/conflict", String, self.syncthing)
        rospy.Subscriber("ogc/feedback_to_rqt", LinkMessage,
                         self.feedback_message)

        rospy.Subscriber("mavros/statustext/recv", StatusText,
                         self.ondemand_sitl)
        rospy.Subscriber("mavros/state", State, self.mode_status_sitl)
        rospy.Subscriber("mavros/vfr_hud", VFR_HUD, self.VFR_HUD_sitl)
        rospy.Subscriber("mavros/mission/waypoints", WaypointList,
                         self.waypoint_sitl)

        # Publisher List
        self.command_publisher = rospy.Publisher("ogc/to_despatcher",
                                                 LinkMessage,
                                                 queue_size=5)

    def create_layout(self):
        '''Populate the UI with the modules from other files'''
        # Create layout for Waypoint scroll window
        scroll = QScrollArea()
        scroll.setMinimumHeight(800)
        scroll.setMinimumWidth(600)
        scroll.setWidgetResizable(True)
        scroll.setWidget(self.WaypointWindow)

        # Create the tab windows for the aircraft-specific information
        self.create_tab_windows([])
        self.tab.currentChanged.connect(self.tab_change)

        # Add all 3 layouts into the main layout
        self._widget.verticalLayout.addWidget(scroll)
        self._widget.verticalLayout2.addWidget(self.tab)
        self._widget.verticalLayout2.addWidget(self.CommandWindow)

    def create_tab_windows(self, active_aircrafts):
        '''Create layout for Summary scroll window'''
        if active_aircrafts == []:
            self.tab = QTabWidget()
            summary_scroll = QScrollArea()
            summary_scroll.setMinimumHeight(500)
            summary_scroll.setMinimumWidth(600)
            summary_scroll.setWidgetResizable(True)
            summary_scroll.setWidget(self.SummaryWindow)
            self.tab.addTab(summary_scroll, "Summary")

        self.SummaryWindow.create_layout(active_aircrafts)
        self.CommandWindow.create_combobox(
            self.aircraft_list
        )  #for checkbox, it needs to full list and not just the added aircraft
        self.WaypointWindow.create_layout(active_aircrafts)

        for i in active_aircrafts:
            self.aircrafts_info["AC" + str(i)] = AircraftInfo(i)
            self.checklist_info["AC" + str(i)] = ChecklistWindow(i)

            tab_key = "aircraft" + str(i) + " scroll"
            self.aircrafts_info[tab_key] = QScrollArea()
            self.aircrafts_info.get(tab_key).setMinimumHeight(500)
            self.aircrafts_info.get(tab_key).setMinimumWidth(600)
            self.aircrafts_info.get(tab_key).setWidgetResizable(True)
            self.aircrafts_info.get(tab_key).setWidget(
                self.aircrafts_info.get("AC" + str(i)))
            self.tab.addTab(self.aircrafts_info.get(tab_key),
                            "Aircraft " + str(i))
            self.tab.show()

        self.tab.setMinimumHeight(500)

    def tab_change(self, i):
        '''Changes the command_window drop-down menu to follow the change in tab'''
        active_aircrafts = self.CommandWindow.ValidIdWindow.valid_ids
        diff_active = list(set(active_aircrafts) - set(self.aircraft_list))
        if not diff_active == []:
            self.aircraft_list = active_aircrafts
            self.create_tab_windows(diff_active)
        for i in range(self.tab.count()):
            if self.tab.tabText(i) != "Summary":
                aircraft_no = int(self.tab.tabText(i)[-1])
                if aircraft_no < i:
                    self.tab.tabBar().moveTab(i, aircraft_no)

        command_window_index = self.tab.currentIndex() - 1
        if command_window_index < 0:
            command_window_index = 0  # If tab is at Summary page, set Combobox to 0th index
        self.CommandWindow.combo_box.setCurrentIndex(command_window_index)

    def feedback_message(self, data):
        status = Communicate()
        status.feedback_message_signal.connect(self.feedback_message_display)
        status.feedback_message_signal.emit(data.data)

    def feedback_message_display(self, data):
        self.PopupMessages.warning_message("Command failed to send", data)

    ################################
    # Create Signal Slot functions #
    ################################
    def regular_payload(self, data):
        aircraft_id = str(data.vehicle_no)
        status = Communicate()
        status.airspeed_signal.connect(self.airspeed_display)
        status.airspeed_signal.emit(data.airspeed, aircraft_id)
        status.alt_signal.connect(self.altitude_display)
        status.alt_signal.emit(data.alt, aircraft_id)
        status.arm_signal.connect(self.arm_status_display)
        status.arm_signal.emit(data.armed, aircraft_id)
        status.batt_signal.connect(self.quad_batt_display)
        status.batt_signal.emit(data.batt, aircraft_id)
        status.fuel_signal.connect(self.fuel_display)
        status.fuel_signal.emit(data.fuel, aircraft_id)
        status.groundspeed_signal.connect(self.groundspeed_display)
        status.groundspeed_signal.emit(data.groundspeed, aircraft_id)
        status.gps_signal.connect(self.gps_display)
        status.gps_signal.emit(data.lat, data.lon, aircraft_id)
        status.mode_signal.connect(self.mode_status_display)
        status.mode_signal.emit(data.mode, aircraft_id)
        status.throttle_signal.connect(self.throttle_display)
        status.throttle_signal.emit(data.throttle, aircraft_id)
        status.vibe_signal.connect(self.vibe_display)
        status.vibe_signal.emit(data.vibe, aircraft_id)
        status.vtol_signal.connect(self.vtol_display)
        status.vtol_signal.emit(data.vtol, aircraft_id)
        status.wp_signal.connect(self.waypoint_display)
        status.wp_signal.emit(data.wp, data.wp_total, aircraft_id)
        status.time_signal.connect(self.time_display)
        status.time_signal.emit(data.header.stamp.secs, aircraft_id)

    def ondemand(self, data):
        # data. data list is i 1 1 0 message
        data_list = data.data.split()
        msg = " ".join(data_list[4:-1])
        aircraft_id = data_list[2]
        status = Communicate()
        if "LinkSwitch" in msg:
            status.ondemand_signal.connect(self.link_status)
        else:
            status.ondemand_signal.connect(self.ondemand_display)
        status.ondemand_signal.emit(
            msg,
            aircraft_id)  # Change the id where to display using headers module

    def ondemand_sitl(self, data):
        status = Communicate()
        status.ondemand_signal.connect(self.ondemand_display)
        status.ondemand_signal.emit(data.text, "1")

    def status_text(self, data):
        status = Communicate()
        status.status_text_signal.connect(self.status_text_display)
        status.status_text_signal.emit(data.data)

    def syncthing(self, data):
        status = Communicate()
        status.syncthing_signal.connect(self.syncthing_conflict)
        status.syncthing_signal.emit(data)

    ####### MAVROS Signal-Slot Functions #######
    def mode_status_sitl(self, data):
        status = Communicate()
        status.mode_sitl_signal.connect(self.mode_status_display_sitl)
        status.mode_sitl_signal.emit(data.mode, "1")
        status.arm_signal.connect(self.arm_status_display)
        status.arm_signal.emit(data.armed, "1")

    def VFR_HUD_sitl(self, data):
        status = Communicate()
        status.airspeed_signal.connect(self.airspeed_display)
        status.airspeed_signal.emit(data.airspeed, "1")
        status.alt_signal.connect(self.altitude_display)
        status.alt_signal.emit(data.altitude, "1")

    def waypoint_sitl(self, data):
        status = Communicate()
        status.waypoint_list_signal.connect(self.waypoint_sitl_display)
        status.waypoint_list_signal.emit(data.waypoints, data.current_seq, "1")

    ##################################################
    # Display information from Signal Slot functions #
    ##################################################
    def airspeed_display(self, airspeed, aircraft_id):
        self.aircrafts_flight_data['airspeed' + aircraft_id] = airspeed
        airspeed = str(round(airspeed, 1)) + " m/s"
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftAirspeed" +
            aircraft_id).setStyleSheet("Color: rgb(255, 0, 0);")
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftAirspeed" + aircraft_id).setPlainText(airspeed)
        self.SummaryWindow.summary_plaintext_dict.get(
            "aircraftAirspeed" + aircraft_id).setPlainText(airspeed)

    def altitude_display(self, altitude, aircraft_id):
        self.aircrafts_flight_data['altitude' + aircraft_id] = altitude
        altitude = str(round(altitude, 1)) + " m"
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftAltitude" + aircraft_id).setPlainText(altitude)
        self.SummaryWindow.summary_plaintext_dict.get(
            "aircraftAltitude" + aircraft_id).setPlainText(altitude)

    def arm_status_display(self, arm_status, aircraft_id):
        self.aircrafts_flight_data['status' + aircraft_id] = arm_status
        if arm_status == "False" or arm_status == 0:
            self.text_to_display = "DISARMED"
        else:
            if self.CommandWindow.arm_status.get('AC' + str(
                    aircraft_id)) == None or self.CommandWindow.arm_status.get(
                        'AC' + str(aircraft_id)) == "DISARMED":
                self.aircrafts_info.get("AC" +
                                        aircraft_id).initial_time = self.time
            self.text_to_display = "ARMED"
        self.CommandWindow.arm_status['AC' +
                                      str(aircraft_id)] = self.text_to_display
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftStatus" + aircraft_id).setPlainText(self.text_to_display)
        self.SummaryWindow.summary_plaintext_dict.get(
            "aircraftStatus" + aircraft_id).setPlainText(self.text_to_display)

    def quad_batt_display(self, data, aircraft_id):
        self.aircrafts_flight_data['battery' + aircraft_id] = data
        data = str(data)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftQuad Battery" + aircraft_id).setPlainText(data)

    def fuel_display(self, data, aircraft_id):
        self.aircrafts_flight_data['fuel' + aircraft_id] = data
        data = str(data)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftFuel Level" + aircraft_id).setPlainText(data)

    def groundspeed_display(self, gndspeed, aircraft_id):
        self.aircrafts_flight_data['groundspeed' + aircraft_id] = gndspeed
        data = str(round(gndspeed, 1)) + " m/s"
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftGroundspeed" + aircraft_id).setPlainText(data)

    def gps_display(self, lat, lon, aircraft_id):
        data = [lat, lon]
        self.aircrafts_flight_data['gps' + aircraft_id] = data
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftGPS" +
            aircraft_id).setPlainText(str(lat) + ", " + str(lon))

    def mode_status_display(self, mode_status, aircraft_id):
        self.aircrafts_flight_data['mode' + aircraft_id] = mode_status
        mode = self.CommandWindow.decoder[
            mode_status]  # Convert the integer to its mode
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftMode" + aircraft_id).setPlainText(mode)
        self.SummaryWindow.summary_plaintext_dict.get(
            "aircraftMode" + aircraft_id).setPlainText(mode)

    def throttle_display(self, data, aircraft_id):
        self.aircrafts_flight_data['throttle' + aircraft_id] = data
        data = str(data)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftThrottle" + aircraft_id).setPlainText(data)

    def vibe_display(self, data, aircraft_id):
        self.aircrafts_flight_data['vibe' + aircraft_id] = data
        data = str(data)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftVibe Status" + aircraft_id).setPlainText(data)

    def vtol_display(self, data, aircraft_id):
        self.aircrafts_flight_data['vtol' + aircraft_id] = data
        data = str(data)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftVTOL Status" + aircraft_id).setPlainText(data)

    def waypoint_display(self, waypoint, total_waypoint, aircraft_id):
        self.aircrafts_flight_data['waypoint' + aircraft_id] = (waypoint,
                                                                total_waypoint)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftTarget Waypoint" + aircraft_id).setPlainText(
                str(waypoint))
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "progress_bar_aircraft" + aircraft_id).setRange(0, total_waypoint)
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "progress_bar_aircraft" + aircraft_id).setValue(waypoint)
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "aircraft" + aircraft_id).setPlainText("Current WP: " +
                                                   str(waypoint) + " out of " +
                                                   str(total_waypoint))

    def time_display(self, AC_time, aircraft_id):
        if self.text_to_display == "DISARMED":
            self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
                "aircraftFlying Time" + aircraft_id).setPlainText("00:00:00")
        else:
            self.time = AC_time  # sync the UI time to the data time
            time_in_seconds = int(self.time) - int(
                self.aircrafts_info.get("AC" + aircraft_id).initial_time)
            minutes = str(time_in_seconds // 60)
            hours = str(time_in_seconds // 3600)
            seconds = str(time_in_seconds - (int(minutes) * 60) -
                          (int(hours) * 3600))
            if int(seconds) < 10:
                seconds = "0" + seconds
            if int(minutes) < 10:
                minutes = "0" + minutes
            if int(hours) < 10:
                hours = "0" + hours
            self.aircrafts_flight_data['time' +
                                       aircraft_id] = self.aircrafts_info.get(
                                           "AC" + aircraft_id).initial_time
            self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
                "aircraftFlying Time" +
                aircraft_id).setPlainText(hours + ":" + minutes + ":" +
                                          seconds)

    def link_status(self, link, aircraft_id):
        link = link[-1]  # extract the status
        if int(link) == 0:
            link = "Telegram"
        elif int(link) == 1:
            link = "SMS"
        elif int(link) == 2:
            link = "SBD"
        else:
            link = "ERR"
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "aircraftlink" + aircraft_id).setPlainText(link)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftLink Status" + aircraft_id).setPlainText(link)

    def status_text_display(self, status_text):
        status = status_text.split(",")
        # time_stamp = int(status[-1]) # Timestamp not needed
        message_type = status[0]
        aircraft_id = status[2]

        info = status[4:-1]
        display_text = "Aircraft {} : {}".format(aircraft_id, str(info[0]))
        self.SummaryWindow.statustext.appendPlainText(display_text)
        self.aircrafts_info.get("AC" + aircraft_id).statustext.appendPlainText(
            display_text)

    def ondemand_display(self, data, aircraft_id):
        status = ""
        text_to_display = "Aircraft {} {}: {}".format(aircraft_id, status,
                                                      data)
        self.SummaryWindow.statustext.appendPlainText(text_to_display)
        self.aircrafts_info.get("AC" + aircraft_id).statustext.appendPlainText(
            text_to_display)

    ####### SITL Display Functions (for developer testing only) #######
    def mode_status_display_sitl(self, mode_status, aircraft_id):
        self.aircrafts_flight_data['mode_sitl' + aircraft_id] = mode_status
        mode_status = str(mode_status)
        self.aircrafts_info.get("AC" + aircraft_id).aircraft_info_dict.get(
            "aircraftMode" + aircraft_id).setPlainText(mode_status)
        self.SummaryWindow.summary_plaintext_dict.get(
            "aircraftMode" + aircraft_id).setPlainText(mode_status)
        self.saved = "[AC {} MODE display] {}".format(int(aircraft_id),
                                                      mode_status)

    def waypoint_sitl_display(self, total, sequence, aircraft_id):
        self.aircrafts_flight_data['waypoint_sitl' +
                                   aircraft_id] = [total, sequence]
        total = len(total) - 1
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "progress_bar_aircraft" + aircraft_id).setRange(0, total)
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "progress_bar_aircraft" + aircraft_id).setValue(sequence)
        self.WaypointWindow.waypoint_plaintext_dict.get(
            "aircraft" + aircraft_id).setPlainText("Current WP: " +
                                                   str(sequence) + " out of " +
                                                   str(total))

    def shortcuts(self):
        '''Create keyboard short-cuts'''
        disarming = QShortcut(self._widget)
        disarming.setKey(Qt.CTRL + Qt.Key_D)
        disarming.activated.connect(self.PopupMessages.emergency_disarm)

        shutdown = QShortcut(self._widget)
        shutdown.setKey(Qt.ALT + Qt.Key_F4)
        shutdown.activated.connect(self.shutdown_plugin)

    def syncthing_conflict(self, file_name):
        heading = "Your edit to the file {} encountered an error".format(
            file_name)
        info_text = "This might be caused due edits happening at the same time \n Please check whether there is another person editing the same file"
        self.PopupMessages.warning_message(heading, info_text)

    def shutdown_plugin(self):
        self.proper_shutdown = 1
        '''Shutdown function'''
        # Shutdown all the checklist windows
        for i in self.aircraft_list:
            self.checklist_info.get("AC" + str(i)).shutdown()
        # Shutdown all identifiers windows
        opened_CommandWindows = [
            x for x in self.CommandWindow.windows_opened.keys()
            if self.CommandWindow.windows_opened.get(x)
        ]
        opened_PopupMessages = [
            x for x in self.PopupMessages.windows_opened.keys()
            if self.PopupMessages.windows_opened.get(x)
        ]
        opened_windows = opened_CommandWindows + opened_PopupMessages
        for i in opened_windows:
            if i == "full_menu":
                self.CommandWindow.full_widget.close()
            elif i == "change_identifiers_dialog":
                self.CommandWindow.change_identifiers_dialog.close()
            elif i == "add_identifiers_dialog":
                self.CommandWindow.add_identifiers_dialog.close()
            elif i == "edit_identifiers_dialog":
                self.CommandWindow.edit_identifiers_dialog.close()
            elif i == "arm window" or i == "disarm window":
                self.CommandWindow.PopupMessages.message.close()
            elif i == "checklist window":
                self.CommandWindow.checklist_info.get(
                    "AC" + str(self.destination_id)).close()
            elif i == "change_valid_ids":
                self.CommandWindow.ValidIdWindow.close()

        self.WaypointWindow.shutdown()
        self.SummaryWindow.shutdown()

    def save_settings(self, plugin_settings, instance_settings):
        with open(self.path, 'r') as lines:
            data = lines.readlines()
        for i in range(len(data)):
            data[i] = "None\n"
        with open(self.path, 'w') as files:
            files.writelines(data)
            files.close()

    def restore_settings(self, plugin_settings, instance_settings):
        filename = "rqt_log.txt"
        self.path = os.path.join(rospkg.RosPack().get_path("yonah_rqt"),
                                 "src/yonah_rqt", filename)
        file_exists = os.path.isfile(self.path)
        if file_exists:
            with open(self.path, 'r') as lines:
                data = lines.readlines()
            for i in data:
                i = i[:-1]
                if i == "None":
                    continue
                else:
                    regpay = i.split(" ")
                    msg = regular.convert_to_rosmsg(regpay)
                    self.regular_payload(msg)
        else:
            rospy.loginfo(
                "rqt: rqt_log file doesn't exist, creating new rqt_log file")
            f = open(self.path, "w+")
            f.write("None")
예제 #3
0
class ProteinQuantification(QMainWindow):
    """
    Application to use different Widgets in one Window:
    First Tab: Welcome tab with information about how the GUI works.
    Second Tab: Config view - here the .ini file can be viewed and edited
    Third Tab: mzMLTable view - the experimental design can be
    viewed and edited.
    Fourth Tab: Fasta view - fasta files can be loaded and inspected
    Fifth Tab: Spec view - ms spectras from loaded mzML files can be seen
    and inspected
    Sixth Tab: mzTabTable view - The result of the ProteomicsLFQ
    is displayed
    """
    def __init__(self):
        QMainWindow.__init__(self)
        self.initUI()
        self.initVars()
        # flag for themetoggle
        self.flag = False
        self.setPalette(self.palette)
        self.setTheme()
        self.setAcceptDrops(True)

    def initUI(self):
        '''
        Sets the window with all applications and widgets.
        '''
        descriptions = desc.descriptions
        widgetlist = {
            "Welcome": [QWidget(), "welcome"],
            "XML-Viewer": [ConfigView(), "cview"],
            "Experimental-Design": [mzMLTableView(), "tview"],
            "Fasta-Viewer": [GUI_FastaViewer(), "fview"],
            "Spec-Viewer": [MultipleSpecView(), "sview"],
            "mzTab-Viewer": [mzTabTableWidget(), "xview"]
        }
        self.view = QTabWidget()
        for wname in widgetlist:
            a = widgetlist[wname][0]
            setattr(self, widgetlist[wname][1], a)
            self.view.addTab(a, wname)

        #self.view.setTabEnabled(5, False)

        self.palette = QPalette()

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        projectMenu = menubar.addMenu('Project')
        parametersMenu = menubar.addMenu('Parameters')
        loadAction = QAction(QIcon("Icons/load_icon.png"), "&Load Project",
                             self)
        loadAction.setShortcut("Ctrl+O")
        saveAction = QAction(QIcon("Icons/save_icon.png"), "&Save Project",
                             self)
        saveAction.setShortcut("Ctrl+S")
        runAction = QAction(QIcon("Icons/run_icon.png"), "&Run in Terminal",
                            self)
        runAction.setShortcut("Ctrl+R")
        Threads = QAction("&Adjust the Threadnumber", self)
        FDR = QAction("&Adjust the protein FDR", self)
        Out = QAction("&Choose outputfiles", self)

        projectMenu.addAction(loadAction)
        projectMenu.addAction(saveAction)
        projectMenu.addAction(runAction)
        parametersMenu.addAction(Threads)
        parametersMenu.addAction(FDR)
        parametersMenu.addAction(Out)

        runAction.triggered.connect(self.runFunction)
        FDR.triggered.connect(self.adjustFDR)
        Threads.triggered.connect(self.adjustThreads)
        Out.triggered.connect(self.chooseOutputfiles)

        saveAction.triggered.connect(self.saveFunction)
        loadAction.triggered.connect(self.loadFunction)

        #themeswitcher
        settingsMenu = menubar.addMenu('Settings')
        switchThemeAction = QAction('Change Theme', self)
        settingsMenu.addAction(switchThemeAction)
        switchThemeAction.triggered.connect(self.switchTheme)

        # Welcome Tab
        normalFont = QFont("Helvetica", 11)
        welcome = QLabel()
        welcome.setText(descriptions["welcome"])
        welcome.setFont(normalFont)
        welcome_layout = QVBoxLayout()
        welcome_layout.addWidget(welcome, 2, Qt.AlignTop)

        iconOpenMs = QPixmap("Icons/IconOpenMS.png")
        iconLabel = QLabel()
        iconLabel.setPixmap(iconOpenMs)

        welcome_layout.addWidget(iconLabel, 4, Qt.AlignTop)
        center_layout = QVBoxLayout()
        view = self.view

        for i in range(1, view.count()):
            print(view.tabText(i))
            label = QLabel()
            label.setText(descriptions[view.tabText(i)])
            label.setFont(normalFont)
            if i == 1:
                center_layout.addWidget(label, 4, Qt.AlignTop)
            else:
                center_layout.addWidget(label, 4)

        central_layout = QHBoxLayout()
        central_layout.addLayout(welcome_layout, 5)
        central_layout.addLayout(center_layout, 5)

        self.welcome.setLayout(central_layout)

        self.setCentralWidget(self.view)
        self.resize(1280, 720)
        self.center()
        self.setWindowTitle('Protein Quantification')
        self.show()
        # print(self.view.count())
        self.view.currentChanged.connect(self.onChange)

    def initVars(self):
        """
        initiates usable variables
        """
        self.ini_loaded = False
        self.tablefile_loaded = False
        self.fasta_loaded = False
        self.mztab_loaded = False
        self.cxml_out = True
        self.msstats_out = True

        self.loaded_dir = ""
        self.loaded_ini = ""
        self.loaded_table = ""
        self.loaded_fasta = ""
        self.loaded_mztab = ""

        self.threads = 1
        self.fdr = 0.3
        self.procdone = False

    def center(self):
        """
        centers the widget to the screen
        """
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def chooseOutputfiles(self):
        """
        Opens a popup window to choose the outputfiles
        If output is generated checkbox is checked.
        """
        # Popup
        self.outputCheckBoxWindow = PopupWindow()
        mainWidget = QWidget()
        mztabCheckbox = QCheckBox("Generate a mzTab outputfile")
        cxmlCheckbox = QCheckBox("Generate a cxml outputfile")
        msstatsCheckbox = QCheckBox("Generate a msstats outputfile")
        layout = QVBoxLayout()
        layout.addWidget(mztabCheckbox)
        layout.addWidget(cxmlCheckbox)
        layout.addWidget(msstatsCheckbox)
        mainWidget.setLayout(layout)
        self.outputCheckBoxWindow.setCentralWidget(mainWidget)
        self.outputCheckBoxWindow.setTitle("Choose Outputfiles")

        # Checkboxstates
        mztabCheckbox.setChecked(True)
        mztabCheckbox.setEnabled(False)

        if self.cxml_out:
            cxmlCheckbox.setChecked(True)

        if self.msstats_out:
            msstatsCheckbox.setChecked(True)

        # Change Checkbox
        cxmlCheckbox.clicked.connect(self.togglecxml)
        msstatsCheckbox.clicked.connect(self.togglemsstats)

    def togglecxml(self):
        if self.cxml_out:
            self.cxml_out = False
        else:
            self.cxml_out = True

    def togglemsstats(self):
        if self.msstats_out:
            self.msstats_out = False
        else:
            self.msstats_out = True

    def adjustFDR(self):
        """
        The user is allowed to change th FDR
        """
        newfdr, ok = QInputDialog.getDouble(
            self, "Adjust the value for the protein FDR",
            "Please specify a double as new FDR value")
        if ok:
            if newfdr > 0:
                if newfdr <= 1:
                    self.fdr = newfdr
                else:
                    QMessageBox.about(
                        self, "Warning", "Please specify a value" +
                        "between 0.0 and 1.0 for the FDR.")
            else:
                QMessageBox.about(
                    self, "Warning",
                    "Please specify a positive" + "value for the FDR.")

    def adjustThreads(self):
        """
        The user is allowed to change the number of threads
        """
        newthreads, ok = QInputDialog.getInt(
            self, "Adjust the number of threads",
            "Please specify the number of threads for the processing")
        if ok:
            if newthreads > 0:
                self.threads = newthreads
            else:
                QMessageBox.about(
                    self, "Warning",
                    "Please specify a positive" + "number of threads.")

    def runFunction(self):
        """
        runs the processing from the GUI in a Terminal
        based on the ProteomicsLFQ command of OpenMS
        """
        self.view.setTabEnabled(5, True)
        #self.saveFunction()
        dlg = QFileDialog(self)
        filePath = dlg.getExistingDirectory()

        self.procdone = False
        outfileprefix, ok = QInputDialog.getText(
            self, "Prefix for outputfiles",
            "Please specify a prefix " + "for the outputfiles")
        outfileprefix = filePath + '/' + outfileprefix
        if ok:

            projectfolder = self.loaded_dir

            mzMLExpLayout = self.tview.getDataFrame()
            try:
                mzMLfiles = mzMLExpLayout['Spectra_Filepath']
                idXMLfiles = []
                for mzML in mzMLfiles:
                    temp = mzML.split(".")
                    idXML = temp[0] + ".idXML"
                    idXMLfiles.append(idXML)
                mzMLidXMLdefined = True
            except KeyError:
                QMessageBox.about(
                    self, "Warning",
                    "Please load or " + "create an Experimental Design first")
                mzMLidXMLdefined = False

            expdesign = self.loaded_table
            dbfasta = self.loaded_fasta
            inifile = self.loaded_ini

            if mzMLidXMLdefined:
                runcall = "ProteomicsLFQ "
                mzMLs = "-in " + " ".join(mzMLfiles)
                idXMLs = " -ids " + " ".join(idXMLfiles)
                design = " -design " + expdesign + " "
                refdb = "-fasta " + dbfasta + " "
                configini = "-ini " + inifile + " "
                threads = "-threads " + str(self.threads) + " "
                fdr = "-proteinFDR " + str(self.fdr) + " "
                out = ""
                if self.cxml_out:
                    out += "-out_cxml " + outfileprefix + ".consensusXML.tmp "
                if self.msstats_out:
                    out += "-out_msstats " + outfileprefix + ".csv.tmp "

                out += "-out " + outfileprefix + ".mzTab.tmp"

                command = (runcall + mzMLs + idXMLs + design + refdb +
                           configini + threads + fdr + out)
                os.chdir(projectfolder)
                os.system(command)
                self.procdone = True
                QMessageBox.about(
                    self, "Information", "Processing has been " +
                    "performed and outputfiles saved to " + "projectfolder")
                mztabfile = outfileprefix + ".mzTab.tmp"
                #print(mztabfile)
                try:
                    self.xview.readFile(mztabfile)
                    self.loaded_mztab = mztabfile
                    self.mztab_loaded = True
                    self.view.setCurrentWidget(self.xview)
                except FileNotFoundError:
                    QMessageBox.about(
                        self, "Warning", "Some Error occurred " +
                        "and no mzTab could be found.")

    def saveFunction(self):
        """
        saves all work from the GUI in chosen folder
        the prefix of the outputfiles can be choosen
        """
        dlg = QFileDialog(self)
        filePath = dlg.getExistingDirectory()

        if filePath:
            filePath = filePath + "/"
            tablePath = ""
            ok = False
            table_empty = self.tview.table.rowCount() <= 0

            if table_empty:
                tablePath = ""
                self.tablefile_loaded = False
                self.tview.tablefile_loaded = False

            if self.tablefile_loaded is False and table_empty is False \
                    and self.tview.tablefile_loaded is False:
                prefix, ok = QInputDialog.getText(
                    self, "Prefix for outputfiles",
                    "Please specify a prefix " + "for the outputfiles")
            if ok:
                tablePath = filePath + prefix + "_design.tsv"
                self.loaded_table = prefix + "_design.tsv"
                self.tablefile_loaded = True

            if self.tablefile_loaded and self.tview.tablefile_loaded is False:
                tablePath = filePath + self.loaded_table

            if self.tview.tablefile_loaded:
                tablePath = filePath + self.tview.loaded_table

            if (ok or self.tablefile_loaded or self.tview.tablefile_loaded) \
                    and table_empty is False:
                df = Tdf.getTable(self.tview)
                fh.exportTable(self.tview, df, tablePath, "tsv")

            xmlPath = filePath + self.loaded_ini
            try:
                self.cview.tree.write(xmlPath)
            except TypeError:
                print("No Config loaded to be saved!")

            if self.loaded_ini != "" and tablePath.split("/")[-1] != "":
                QMessageBox.about(
                    self, "Successfully saved!", "Files have been saved as: " +
                    self.loaded_ini + ", " + tablePath.split("/")[-1])
            elif self.loaded_ini != "":
                QMessageBox.about(self, "Successfully saved!",
                                  "ini has been saved as: " + self.loaded_ini)
            elif tablePath.split("/")[-1] != "":
                QMessageBox.about(
                    self, "Successfully saved!",
                    "Table has been saved as: " + tablePath.split("/")[-1])

    def loadFunction(self, filePath: str = ""):
        """
        loads all files (.tsv .ini, .fasta) from a given
        directory.
        If .tsv file is not present the experimental design is
        filled with mzMl files

        If no .ini file is present default ini file is written
        and is loaded automatically
        """
        if not filePath:
            dlg = QFileDialog(self)
            filePath = dlg.getExistingDirectory()
        self.loaded_dir = filePath
        self.sview.fillTable(filePath)
        if filePath:
            try:
                self.tsvfiles = glob.glob('*.tsv')
                if len(self.tsvfiles) > 1:
                    QMessageBox.about(
                        self, "Sorry!", "There are multiple '.tsv-'"
                        "files in the specified folder. "
                        "Please choose the one you intent "
                        "to use.")
                    dial = QFileDialog(self)
                    newFilePath = dial.getOpenFileName(self, "Choose .tsv",
                                                       filePath,
                                                       "Tables (*.tsv)")
                    if newFilePath[0] != '':
                        newFile = newFilePath[0].split("/")[-1]
                        self.tsvfiles = [newFile]
                    else:
                        QMessageBox.about(
                            self, "Sorry!", "Nothing was choosen. "
                            "Therefore no '.tsv'-file was "
                            "loaded. ")
                        self.tsvfiles = []
                for file in self.tsvfiles:
                    df = fh.importTable(self.tview, file)
                    Tdf.setTable(self.tview, df)
                    self.tview.drawTable()
                    self.loaded_table = file
                    self.tablefile_loaded = True

            except TypeError:
                "No '.tsv' or '.csv'-file could be loaded."

            if self.tablefile_loaded is False:
                try:
                    self.tview.loadDir(filePath)
                    self.tablefile_loaded = True
                except TypeError:
                    print("Could not load '.mzMl'-files.")

            try:
                self.iniFiles = glob.glob('*.ini')
                if len(self.iniFiles) > 1:
                    QMessageBox.about(
                        self, "Sorry!", "There are multiple '.ini'-"
                        "files in the specified folder. "
                        "Please choose the one you intent "
                        "to use.")
                    dial = QFileDialog(self)
                    newFilePath = dial.getOpenFileName(self, "Choose .ini",
                                                       filePath,
                                                       "Config (*.ini)")
                    if newFilePath[0] != '':
                        newFile = newFilePath[0].split("/")[-1]
                        self.iniFiles = [newFile]
                    else:
                        QMessageBox.about(
                            self, "Sorry!", "Nothing was choosen. "
                            "Therefore no '.ini'-file was "
                            "loaded. ")
                        self.iniFiles = []
                for file in self.iniFiles:
                    self.cview.generateTreeModel(file)
                    self.loaded_ini = file
                    self.ini_loaded = True
            except TypeError:
                print("Could not load .ini file.")

            if self.ini_loaded is False:
                try:
                    runcall = "ProteomicsLFQ "
                    writeIniFile = "-write_ini "
                    out = "Config.ini"
                    command = (runcall + writeIniFile + out)
                    os.chdir(filePath)
                    os.system(command)
                    iniFiles = glob.glob('*.ini')
                    for file in iniFiles:
                        self.cview.generateTreeModel(file)
                        self.loaded_ini = file
                        self.ini_loaded = True
                except TypeError:
                    print("Could not write and load default '.ini'-file.")

            try:
                self.fastafiles = glob.glob('*fasta')
                if len(self.fastafiles) > 1:
                    QMessageBox.about(
                        self, "Sorry!", "There are multiple '.fasta'-"
                        "files in the specified folder. "
                        "Please choose the one you intent "
                        "to use.")
                    dial = QFileDialog(self)
                    newFilePath = dial.getOpenFileName(
                        self, "Choose .fasta", filePath,
                        "Proteindata (*.fasta)")
                    if newFilePath[0] != '':
                        newFile = newFilePath[0].split("/")[-1]
                        self.fastafiles = [newFile]
                    else:
                        QMessageBox.about(
                            self, "Sorry!", "Nothing was choosen. "
                            "Therefore, no '.fasta'-file "
                            "was loaded. ")
                        self.fastafiles = []
                for file in self.fastafiles:
                    self.fview.loadFile(file)
                    self.loaded_fasta = file
                    self.fasta_loaded = True
            except TypeError:
                print("Could not load '.fasta'-file.")

    def setTheme(self):
        """
        Sets theme based on flag state, light or dark modes are possible.
        Default is light theme.
        """
        p = self.palette
        if not self.flag:
            # lightmode
            p.setColor(QPalette.Window, Qt.white)
            p.setColor(QPalette.Background, Qt.white)
            p.setColor(QPalette.WindowText, Qt.black)
            p.setColor(QPalette.Base, Qt.white)
            p.setColor(QPalette.AlternateBase, Qt.white)
            p.setColor(QPalette.ToolTipBase, Qt.black)
            p.setColor(QPalette.ToolTipText, Qt.black)
            p.setColor(QPalette.Text, Qt.black)
            p.setColor(QPalette.Button, Qt.white)
            p.setColor(QPalette.ButtonText, Qt.black)
            p.setColor(QPalette.BrightText, Qt.red)
            p.setColor(QPalette.Link, QColor(213, 125, 37))
            p.setColor(QPalette.Highlight, QColor(213, 125, 37))
            p.setColor(QPalette.HighlightedText, Qt.white)
        else:
            # darkmode
            p.setColor(QPalette.Window, QColor(53, 53, 53))
            p.setColor(QPalette.WindowText, Qt.white)
            p.setColor(QPalette.Base, QColor(25, 25, 25))
            p.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            p.setColor(QPalette.ToolTipBase, Qt.white)
            p.setColor(QPalette.ToolTipText, Qt.white)
            p.setColor(QPalette.Text, Qt.white)
            p.setColor(QPalette.Button, QColor(53, 53, 53))
            p.setColor(QPalette.ButtonText, Qt.white)
            p.setColor(QPalette.BrightText, Qt.red)
            p.setColor(QPalette.Link, QColor(42, 130, 218))
            p.setColor(QPalette.Highlight, QColor(42, 130, 218))
            p.setColor(QPalette.HighlightedText, Qt.black)
        self.setPalette(p)

    def dragEnterEvent(self, event):
        e = event
        data = e.mimeData()
        urls = data.urls()

        if urls and urls[0].scheme() == "file":
            e.acceptProposedAction()
        else:
            e.ignore()

    def dragMoveEvent(self, event):
        e = event
        data = e.mimeData()
        urls = data.urls()

        if urls and urls[0].scheme() == "file":
            e.acceptProposedAction()
        else:
            e.ignore()

    def dropEvent(self, event):
        e = event
        data = e.mimeData()
        urls = data.urls()

        if urls and urls[0].scheme() == "file":
            #welcome page
            if self.view.currentIndex() == 0:
                filetype = "directory"
                filepath = self.urlHandler(urls[0].path())
                if os.path.isdir(filepath):
                    self.loadFunction(filepath)
                else:
                    self.displayDragNDropError(filetype)
            #xmlviewer
            elif self.view.currentIndex() == 1:
                files = [self.urlHandler(u.path()) for u in urls]
                self.cview.dragDropEvent(files)
            #experimental design
            elif self.view.currentIndex() == 2:
                filetype = ["mzML", "tsv", "csv"]
                filepath = self.urlHandler(urls[0].path())
                if filepath[-4:] == filetype[0]:
                    self.tview.loadFile(filepath)
                elif (filepath[-3:] == filetype[1]) or (filepath[-3:]
                                                        == filetype[2]):
                    self.tview.importBtn(filepath)
                else:
                    self.displayDragNDropError("", filetype)
            #fasta viewer
            elif self.view.currentIndex() == 3:
                filepath = self.urlHandler(urls[0].path())
                filetype = "fasta"
                if filepath[-5:] == filetype:
                    self.fview.loadFile(filepath)
                else:
                    self.displayDragNDropError(filetype)

            #specviewer
            elif self.view.currentIndex() == 4:
                filetype = "mzML"
                filepath = self.urlHandler(urls[0].path())
                if filepath[-4:] == filetype:
                    self.sview.sview.openFileDialog(filepath)
                else:
                    self.displayDragNDropError(filetype)
            elif self.view.currentIndex() == 5:
                filetype = "mzTab"
                filepath = self.urlHandler(urls[0].path())
                if filepath[-5:] == filetype:
                    self.xview.readFile(filepath)
                else:
                    self.displayDragNDropError(filetype)
        else:
            e.ignore()

    def displayDragNDropError(self, filetype: str, mul: list = []):
        """ 
        displays an error message in a messagebox detailing what went wrong
        """
        message = ""
        if not mul:
            if filetype == "directory":
                message = "a directory to load a project"
            else:
                message = "'." + filetype + "'-files"
        else:
            message += "'." + mul[0] + "'"
            for file in mul[1:-1]:
                message += ", '." + file + "'"
            message += " or " + mul[-1] + "'-files"
        dialog = QMessageBox()
        dialog.setWindowTitle("Error: Invalid File")
        dialog.setText("Please only use " + message)
        dialog.setIcon(QMessageBox.Warning)
        dialog.exec_()

    def urlHandler(self, url):
        opsys = platform.system()
        if (opsys == "Linux"):
            return str(url)
        if (opsys == "Windows"):
            return str(url)[1:]
        if (opsys == "Darwin"):
            return str(url)  # to be tested

    def onChange(self):
        """
        this function detects if a tab has been changed.
        for debugging purposes.
        """
        print(self.view.currentIndex())

    def switchTheme(self):
        """
        Toggles between dark and light theme.
        """

        self.flag = not self.flag
        self.setTheme()
예제 #4
0
class MainWindow(QMainWindow):
    OnlineHelpUrl = QUrl("https://GridTools.github.io/serialbox/sdb.html")

    def __init__(self):
        super().__init__()
        Logger.info("Setup main window")

        self.__input_serializer_data = SerializerData("Input Serializer")
        self.__input_stencil_data = StencilData(self.__input_serializer_data)

        self.__reference_serializer_data = SerializerData(
            "Reference Serializer")
        self.__reference_stencil_data = StencilData(
            self.__reference_serializer_data)

        self.__stencil_field_mapper = StencilFieldMapper(
            self.__input_stencil_data, self.__reference_stencil_data,
            GlobalConfig()["async"])

        self.__file_system_watcher = QFileSystemWatcher()
        self.__file_system_watcher.directoryChanged[str].connect(
            self.popup_reload_box)
        self.__file_system_watcher_last_modify = time()

        # Load from session?
        self.__session_manager = SessionManager()

        if GlobalConfig()["default_session"]:
            self.__session_manager.load_from_file()

        self.__session_manager.set_serializer_data(
            self.__input_serializer_data)
        self.__session_manager.set_serializer_data(
            self.__reference_serializer_data)

        # Setup GUI
        self.setWindowTitle('sdb - stencil debugger (%s)' %
                            Version().sdb_version())
        self.resize(1200, 600)

        if GlobalConfig()["center_window"]:
            self.center()

        if GlobalConfig()["move_window"]:
            self.move(GlobalConfig()["move_window"])

        self.setWindowIcon(Icon("logo-small.png"))
        self.init_menu_tool_bar()

        # Tabs
        self.__tab_highest_valid_state = TabState.Setup
        self.__widget_tab = QTabWidget(self)

        # Setup tab
        self.__widget_tab.addTab(
            SetupWindow(self, self.__input_serializer_data,
                        self.__reference_serializer_data), "Setup")

        # Stencil tab
        self.__widget_tab.addTab(
            StencilWindow(self, self.__stencil_field_mapper,
                          self.__input_stencil_data,
                          self.__reference_stencil_data), "Stencil")

        # Result tab
        self.__widget_tab.addTab(
            ResultWindow(self,
                         self.__widget_tab.widget(TabState.Stencil.value),
                         self.__stencil_field_mapper), "Result")

        # Error tab
        self.__widget_tab.addTab(ErrorWindow(self), "Error")

        self.__widget_tab.currentChanged.connect(self.switch_to_tab)

        self.__widget_tab.setTabEnabled(TabState.Setup.value, True)
        self.__widget_tab.setTabEnabled(TabState.Stencil.value, False)
        self.__widget_tab.setTabEnabled(TabState.Result.value, False)
        self.__widget_tab.setTabEnabled(TabState.Error.value, False)

        self.__widget_tab.setTabToolTip(TabState.Setup.value,
                                        "Setup Input and Refrence Serializer")
        self.__widget_tab.setTabToolTip(
            TabState.Stencil.value,
            "Set the stencil to compare and define the mapping of the fields")
        self.__widget_tab.setTabToolTip(TabState.Result.value,
                                        "View to comparison result")
        self.__widget_tab.setTabToolTip(
            TabState.Error.value,
            "Detailed error desscription of the current field")

        self.__tab_current_state = TabState.Setup
        self.set_tab_highest_valid_state(TabState.Setup)
        self.switch_to_tab(TabState.Setup)

        self.setCentralWidget(self.__widget_tab)

        # If the MainWindow is closed, kill all popup windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        Logger.info("Starting main loop")
        self.show()

    def init_menu_tool_bar(self):
        Logger.info("Setup menu toolbar")

        action_exit = QAction("Exit", self)
        action_exit.setShortcut("Ctrl+Q")
        action_exit.setStatusTip("Exit the application")
        action_exit.triggered.connect(self.close)

        action_about = QAction("&About", self)
        action_about.setStatusTip("Show the application's About box")
        action_about.triggered.connect(self.popup_about_box)

        action_save_session = QAction(Icon("filesave.png"), "&Save", self)
        action_save_session.setStatusTip("Save current session")
        action_save_session.setShortcut("Ctrl+S")
        action_save_session.triggered.connect(self.save_session)

        action_open_session = QAction(Icon("fileopen.png"), "&Open", self)
        action_open_session.setShortcut("Ctrl+O")
        action_open_session.setStatusTip("Open session")
        action_open_session.triggered.connect(self.open_session)

        action_help = QAction(Icon("help.png"), "&Online Help", self)
        action_help.setStatusTip("Online Help")
        action_help.setToolTip("Online Help")
        action_help.triggered.connect(self.go_to_online_help)

        self.__action_continue = QAction(Icon("next_cursor.png"), "Continue",
                                         self)
        self.__action_continue.setStatusTip("Continue to next tab")
        self.__action_continue.triggered.connect(self.switch_to_next_tab)
        self.__action_continue.setEnabled(True)

        self.__action_back = QAction(Icon("prev_cursor.png"), "Back", self)
        self.__action_back.setStatusTip("Back to previous tab")
        self.__action_back.triggered.connect(self.switch_to_previous_tab)
        self.__action_back.setEnabled(False)

        self.__action_reload = QAction(Icon("step_in.png"), "Reload", self)
        self.__action_reload.setStatusTip(
            "Reload Input and Reference Serializer")
        self.__action_reload.setShortcut("Ctrl+R")
        self.__action_reload.triggered.connect(self.reload_serializer)
        self.__action_reload.setEnabled(False)

        self.__action_try_switch_to_error_tab = QAction(
            Icon("visualize.png"), "Detailed error description", self)
        self.__action_try_switch_to_error_tab.setStatusTip(
            "Detailed error desscription of the current field")
        self.__action_try_switch_to_error_tab.triggered.connect(
            self.try_switch_to_error_tab)
        self.__action_try_switch_to_error_tab.setEnabled(False)

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        self.statusBar()

        file_menu = menubar.addMenu('&File')
        file_menu.addAction(action_open_session)
        file_menu.addAction(action_save_session)
        file_menu.addAction(action_exit)

        edit_menu = menubar.addMenu('&Edit')
        edit_menu.addAction(self.__action_back)
        edit_menu.addAction(self.__action_continue)
        edit_menu.addAction(self.__action_reload)

        help_menu = menubar.addMenu('&Help')
        help_menu.addAction(action_about)
        help_menu.addAction(action_help)

        toolbar = self.addToolBar("Toolbar")
        toolbar.addAction(action_help)
        toolbar.addAction(action_open_session)
        toolbar.addAction(action_save_session)
        toolbar.addAction(self.__action_back)
        toolbar.addAction(self.__action_continue)
        toolbar.addAction(self.__action_reload)
        toolbar.addAction(self.__action_try_switch_to_error_tab)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def closeEvent(self, event):
        self.__session_manager.update_serializer_data(
            self.__input_serializer_data)
        self.__session_manager.update_serializer_data(
            self.__reference_serializer_data)

        if GlobalConfig()["default_session"]:
            self.__session_manager.store_to_file()

    # ===----------------------------------------------------------------------------------------===
    #   TabWidgets
    # ==-----------------------------------------------------------------------------------------===

    def tab_widget(self, idx):
        return self.__widget_tab.widget(
            idx if not isinstance(idx, TabState) else idx.value)

    def switch_to_tab(self, tab):
        idx = tab.value if isinstance(tab, TabState) else tab
        if self.__tab_current_state == TabState(idx):
            return

        Logger.info("Switching to %s tab" % TabState(idx).name)
        self.__tab_current_state = TabState(idx)

        self.__widget_tab.setCurrentIndex(idx)
        self.tab_widget(idx).make_update()

        self.__action_try_switch_to_error_tab.setEnabled(
            TabState(idx) == TabState.Result)

        # Error tab is always disabled if not in "Error"
        self.__widget_tab.setTabEnabled(TabState.Error.value,
                                        TabState(idx) == TabState.Error)

        # First tab
        if idx == 0:
            self.__action_continue.setEnabled(True)
            self.__action_back.setEnabled(False)
        # Last tab
        elif idx == self.__widget_tab.count() - 1:
            self.__action_continue.setEnabled(False)
            self.__action_back.setEnabled(True)
        # Middle tab
        else:
            self.__action_continue.setEnabled(True)
            self.__action_back.setEnabled(True)

    def set_tab_highest_valid_state(self, state):
        """Set the state at which the data is valid i.e everything <= self.valid_tab_state is valid
        """
        self.__tab_highest_valid_state = state
        self.enable_tabs_according_to_tab_highest_valid_state()

    def enable_tabs_according_to_tab_highest_valid_state(self):
        """Enable/Disable tabs according to self.__tab_highest_valid_state
        """
        if self.__tab_highest_valid_state == TabState.Setup:
            self.__widget_tab.setTabEnabled(TabState.Setup.value, True)
            self.__widget_tab.setTabEnabled(TabState.Stencil.value, False)
            self.__widget_tab.setTabEnabled(TabState.Result.value, False)
            self.__widget_tab.setTabEnabled(TabState.Error.value, False)

            self.__action_try_switch_to_error_tab.setEnabled(False)

            watched_directories = self.__file_system_watcher.directories()
            if watched_directories:
                self.__file_system_watcher.removePaths(
                    self.__file_system_watcher.directories())

        elif self.__tab_highest_valid_state == TabState.Stencil:

            self.__file_system_watcher.addPath(
                self.__input_serializer_data.serializer.directory)
            self.__file_system_watcher.addPath(
                self.__reference_stencil_data.serializer.directory)

            self.__widget_tab.setTabEnabled(TabState.Setup.value, True)
            self.__widget_tab.setTabEnabled(TabState.Stencil.value, True)
            self.__widget_tab.setTabEnabled(TabState.Result.value, False)
            self.__widget_tab.setTabEnabled(TabState.Error.value, False)

            self.__widget_tab.widget(
                TabState.Stencil.value).initial_field_match()

            self.__action_reload.setEnabled(True)
            self.__action_try_switch_to_error_tab.setEnabled(False)

        elif self.__tab_highest_valid_state == TabState.Result:
            self.__widget_tab.setTabEnabled(TabState.Setup.value, True)
            self.__widget_tab.setTabEnabled(TabState.Stencil.value, True)
            self.__widget_tab.setTabEnabled(TabState.Result.value, True)
            self.__widget_tab.setTabEnabled(TabState.Error.value, True)

            self.__action_try_switch_to_error_tab.setEnabled(True)

        elif self.__tab_highest_valid_state == TabState.Error:
            self.__widget_tab.setTabEnabled(TabState.Setup.value, True)
            self.__widget_tab.setTabEnabled(TabState.Stencil.value, True)
            self.__widget_tab.setTabEnabled(TabState.Result.value, True)
            self.__action_try_switch_to_error_tab.setEnabled(False)

    def switch_to_next_tab(self):
        self.__widget_tab.currentWidget().make_continue()

    def switch_to_previous_tab(self):
        self.__widget_tab.currentWidget().make_back()

    def try_switch_to_error_tab(self):
        if self.__widget_tab.widget(
                TabState.Result.value).try_switch_to_error_tab():
            self.__widget_tab.setTabEnabled(TabState.Error.value, True)

    def error_window_set_result_data(self, result_data):
        self.__widget_tab.widget(
            TabState.Error.value).set_result_data(result_data)

    # ===----------------------------------------------------------------------------------------===
    #   PopupWidgets
    # ==-----------------------------------------------------------------------------------------===

    def popup_about_box(self):
        self.__about_widget = PopupAboutWidget(self)

    def popup_error_box(self, msg):
        Logger.error(
            msg.replace("<b>",
                        "").replace("</b>",
                                    "").replace("<br />",
                                                ":").replace("<br/>", ":"))

        msg_box = QMessageBox()
        msg_box.setWindowTitle("Error")
        msg_box.setIcon(QMessageBox.Critical)
        msg_box.setText(msg)
        msg_box.setStandardButtons(QMessageBox.Ok)
        reply = msg_box.exec_()  # Blocking

    def popup_reload_box(self, path):
        self.__file_system_watcher.blockSignals(True)
        reply = QMessageBox.question(
            self, "Reload serializer?",
            "The path \"%s\" has changed.\nDo want to reload the serializers?"
            % path, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            self.reload_serializer()

        self.__file_system_watcher.blockSignals(False)

    # ===----------------------------------------------------------------------------------------===
    #   Session manager
    # ==-----------------------------------------------------------------------------------------===

    def save_session(self):
        Logger.info("Try saving current session")

        dialog = QFileDialog(self, "Save current session")
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setDefaultSuffix("json")
        dialog.setDirectory(getcwd())

        if not dialog.exec_():
            Logger.info("Abort saving current session")
            return

        filename = dialog.selectedFiles()
        self.__session_manager.update_serializer_data(
            self.__input_serializer_data)
        self.__session_manager.update_serializer_data(
            self.__reference_serializer_data)

        ret, msglist = self.__session_manager.store_to_file(filename[0])
        if not ret:
            self.popup_error_box("Failed to save configuration file: %s\n%s " %
                                 (filename[0], msglist[0]))

    def open_session(self):
        Logger.info("Try opening session")
        filename = QFileDialog.getOpenFileName(
            self, "Open Session", getcwd(), "JSON configuration (*.json)")[0]

        if filename is None or filename is "":
            Logger.info("Abort opening session")
            return

        ret, msglist = self.__session_manager.load_from_file(filename)
        if not ret:
            self.popup_error_box("Failed to load configuration file: %s\n%s " %
                                 (filename, msglist[0]))
        else:
            Logger.info("Successfully opened session")
            self.__session_manager.set_serializer_data(
                self.__input_serializer_data)
            self.__session_manager.set_serializer_data(
                self.__reference_serializer_data)
            self.switch_to_tab(TabState.Setup)

    @property
    def session_manager(self):
        return self.__session_manager

    # ===----------------------------------------------------------------------------------------===
    #   Reload Serializer
    # ==-----------------------------------------------------------------------------------------===

    def reload_serializer(self):
        Logger.info("Reloading serializers")
        try:
            self.__input_serializer_data.reload()
            self.__reference_serializer_data.reload()

            if self.__widget_tab.currentIndex() == TabState.Error.value:
                self.switch_to_tab(TabState.Result)

            self.__widget_tab.currentWidget().make_update()

        except RuntimeError as e:
            self.popup_error_box(str(e))
            self.set_tab_highest_valid_state(TabState.Setup)
            self.switch_to_tab(TabState.Setup)
            self.__widget_tab.currentWidget().make_update()

    # ===----------------------------------------------------------------------------------------===
    #   Online help
    # ==-----------------------------------------------------------------------------------------===

    def go_to_online_help(self):
        Logger.info("Opening online help")
        QDesktopServices.openUrl(MainWindow.OnlineHelpUrl)
예제 #5
0
class Tabs(QWidget, QThread):
    def __init__(self, callback):
        super().__init__()

        self.layout = QHBoxLayout(self)  # Change main layout to Vertical
        # Initialize tab screen
        self.tabs = QTabWidget()  # TODO: This is topright
        font = QFont(editor['tabFont'])
        font.setPointSize(
            editor["tabFontSize"])  # This is the tab font and font size
        self.tabs.setFont(font)

        self.IPyconsole = ConsoleWidget(
        )  # Create IPython widget TODO: This is bottom, this is thread1

        self.Console = Console(
        )  # This is the terminal widget and the SECOND thread

        self.directory = Directory(callback)  # TODO: This is top left
        self.directory.clearSelection()
        self.tabCounter = []
        # Add tabs
        self.tab_layout = QHBoxLayout(
        )  # Create new layout for original tab layout
        self.tab_layout.addWidget(self.tabs)  # Add tab widget to tab layout

        self.tabs.setTabsClosable(True)
        self.tabs.setMovable(
            editor['tabMovable'])  # Let's you make the tabs movable

        if editor[
                'tabShape'] is True:  # If tab shape is true then they have this rounded look
            self.tabs.setTabShape(1)

        else:
            self.tabs.setTabShape(0)  # If false, it has this boxy look

        self.tabs.tabCloseRequested.connect(self.closeTab)

        # Add Console
        self.console_layout = QHBoxLayout()  # Create console layout
        self.console_layout.addWidget(
            self.IPyconsole)  # Add console to console layout

        # Build Layout
        self.layout.addLayout(
            self.tab_layout)  # Adds 'TOP' layout : tab + directory

        # Creating horizontal splitter
        self.splitterH = QSplitter(Qt.Horizontal)

        # Creating vertical splitter
        self.splitterV = QSplitter(Qt.Vertical)

        self.splitterV.addWidget(self.splitterH)
        self.layout.addWidget(self.splitterV)
        self.splitterV.setSizes([300, 10])
        self.setLayout(self.layout)  # Sets layout of QWidget

        self.closeShortcut = QShortcut(
            QKeySequence(editor["closeTabShortcut"]), self)
        self.closeShortcut.activated.connect(self.closeTabShortcut)

        self.hideDirectory()

    @pyqtSlot()
    def closeTabShortcut(self):
        self.index = self.tabs.currentIndex()
        self.closeTab(self.index)

    def closeTab(self, index):
        tab = self.tabs.widget(index)

        tab.deleteLater()
        self.tabCounter.pop(index)
        self.tabs.removeTab(index)

    def showDirectory(self):
        self.directory.setVisible(True)
        self.tab_layout.removeWidget(self.tabs)
        self.splitterH.addWidget(
            self.directory
        )  # Adding that directory widget in the Tab class BEFORE the tabs
        self.splitterH.addWidget(
            self.tabs
        )  # Adding tabs, now the directory tree will be on the left

    def hideDirectory(self):
        self.tab_layout.removeWidget(self.directory)
        self.directory.setVisible(False)

    """
    Because the root layouts are set all you have to do now is just add/remove widgets from the parent layout associated.
    This keeps the UI order set as intended as built above when initialized.
    """

    def showConsole(self):
        pass

    def currentTab(self):
        return self.tabs.currentWidget()
예제 #6
0
class Assembler(QMainWindow):
    def __init__(self, parent=None):
        super(Assembler, self).__init__(parent)
        self.resize(800, 600)
        self.filename  = None
        self.filetuple = None
        self.dirty = False  # Refers to Data Page only.
        self.nb = None
        centralwidget = QWidget(self)
        gridLayout = QGridLayout(centralwidget)
        self.tabWidget = QTabWidget(centralwidget)


        # textbox

        self.tab = QWidget()
        font = QFont()
        font.setFamily("Inconsolata")
        font.setPointSize(14)
        self.tab.setFont(font)
        gridLayout_3 = QGridLayout(self.tab)
        self.plainTextEdit = QPlainTextEdit(self.tab)
        self.plainTextEdit.installEventFilter(self)
        self.plainTextEdit.setAcceptDrops(True)
        gridLayout_3.addWidget(self.plainTextEdit, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab, "")





        self.tab_2 = QWidget()
        self.tab_2.setFont(font)
        gridLayout_2 = QGridLayout(self.tab_2)
        self.plainTextEdit_2 = QPlainTextEdit(self.tab_2)
        gridLayout_2.addWidget(self.plainTextEdit_2, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab_2, "")

        self.tab_3 = QWidget()
        self.tab_3.setFont(font)
        gridLayout_3 = QGridLayout(self.tab_3)
        self.checkbox = QCheckBox("Cloning genes by tailed primers (no pYPKa_A vectors constructed)")
        self.checkbox.setChecked(True)
        gridLayout_3.addWidget(self.checkbox, 0, 0, 0, 0)
        self.tabWidget.addTab(self.tab_3, "")

        gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
        self.setCentralWidget(centralwidget)
        menubar = QMenuBar(self)
        menubar.setGeometry(QRect(0, 0, 800, 29))
        menu_File = QMenu(menubar)
        self.menu_Solve = QMenu(menubar)
        self.menu_Help = QMenu(menubar)
        self.setMenuBar(menubar)
        self.statusbar = QStatusBar(self)
        self.setStatusBar(self.statusbar)
        self.action_New = QAction(self)
        self.actionSave_As = QAction(self)
        self.action_Save = QAction(self)
        self.action_Open = QAction(self)
        self.action_Quit = QAction(self)
        self.action_About = QAction(self)
        self.actionShow_CCPL = QAction(self)
        self.action_Solve  = QAction(self)
        self.action_OpenNB = QAction(self)
        self.action_CCPL = QAction(self)
        self.action_Help = QAction(self)
        menu_File.addAction(self.action_New)
        menu_File.addAction(self.action_Open)
        menu_File.addAction(self.actionSave_As)
        menu_File.addAction(self.action_Save)
        menu_File.addSeparator()
        menu_File.addAction(self.action_Quit)
        self.menu_Solve.addAction(self.action_Solve)
        self.menu_Solve.addAction(self.action_OpenNB)
        self.menu_Help.addAction(self.action_About)
        #self.menu_Help.addAction(self.action_CCPL)
        #self.menu_Help.addAction(self.action_Help)
        menubar.addAction(menu_File.menuAction())
        menubar.addAction(self.menu_Solve.menuAction())
        menubar.addAction(self.menu_Help.menuAction())

        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),\
                                   "Data Page")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2),\
                                   "Assembly log")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3),\
                                   "Settings")
        menu_File.setTitle("&File")
        self.menu_Solve.setTitle("&Assemble")
        self.menu_Help.setTitle("&About")
        self.tabWidget.setCurrentIndex(0)
        self.action_New.setText("&New")
        self.action_Open.setText("&Open")
        self.actionSave_As.setText("Save &As")
        self.action_Save.setText("&Save")
        self.action_Quit.setText("&Quit")
        self.action_Solve.setText("&Assemble")
        self.action_OpenNB.setText("&Open &pathway")
        self.action_About.setText("&About")
        #self.action_CCPL.setText("&CCPL")
        #self.action_Help.setText("&Help")
        self.action_Quit.triggered.connect(self.close)
        allToolBar = self.addToolBar("AllToolBar")
        allToolBar.setObjectName("AllToolBar")
        self.addActions(allToolBar, (self.action_Open,
                                     self.actionSave_As,
                                     self.action_Save,
                                     self.action_Solve,
                                     self.action_OpenNB,
                                     self.action_Quit ))
        self.action_New.triggered.connect(self.fileNew)
        self.action_Open.triggered.connect(self.fileOpen)
        self.actionSave_As.triggered.connect(self.fileSaveAs)
        self.action_Save.triggered.connect(self.fileSave)
        self.action_Solve.triggered.connect(self.solveAssembly)
        self.action_OpenNB.triggered.connect(self.openNB)
        self.action_About.triggered.connect(self.aboutBox)
        #self.action_CCPL.triggered.connect(self.displayCCPL)
        #self.action_Help.triggered.connect(self.help)
        self.plainTextEdit.textChanged.connect(self.setDirty)
        self.action_New = self.editAction(self.action_New, None,\
                            'ctrl+N', 'filenew', 'New File.')
        self.action_Open = self.editAction(self.action_Open, None,
                            'ctrl+O', 'fileopen', 'Open File.')
        self.actionSave_As = self.editAction(self.actionSave_As,\
                            None, 'ctrl+A', 'filesaveas',\
                            'Save and Name File.')
        self.action_Save = self.editAction(self.action_Save, None,
                            'ctrl+S', 'filesave', 'Save File.')
        self.action_Solve = self.editAction(self.action_Solve, None,
                            '', 'solve', 'Assemble.')
        self.action_OpenNB = self.editAction(self.action_OpenNB, None,
                            '', 'ipynb', 'Open pathway.')
        self.action_About = self.editAction(self.action_About, None,
                            'ctrl+B', 'about','Pop About Box.')
        self.action_CCPL = self.editAction(self.action_CCPL, None,
                            'ctrl+G', 'licence', 'Show Licence')
        self.action_Help = self.editAction(self.action_Help, None,
                            'ctrl+H', 'help', 'Show Help Page.')
        self.action_Quit =  self.editAction(self.action_Quit, None,
                            'ctrl+Q', 'quit', 'Quit the program.')
        self.plainTextEdit_2.setReadOnly(True)

        self.setWindowTitle("ypkpathway")
        self.setWindowIcon(QIcon( resource_filename("ypkpathway","icons/ypkpathway.png")))
        self.plainTextEdit.setFocus()

    def eventFilter(self, object, event):
        #print(event.type(), QEvent.DragEnter, object, self.plainTextEdit)
        if (object is self.plainTextEdit):
            if (event.type() == QEvent.DragEnter):
                if event.mimeData().hasUrls():
                    event.accept()   # must accept the dragEnterEvent or else the dropEvent can't occur !!!
                    print("accept")
                else:
                    event.ignore()
                    print("ignore")
            if (event.type() == QEvent.Drop):
                if event.mimeData().hasUrls():   # if file or link is dropped
                    urlcount = len(event.mimeData().urls())  # count number of drops
                    url = event.mimeData().urls()[0]   # get first url
                    object.setPlainText('abc')   # assign first url to editline
                    event.accept()  # doesnt appear to be needed
                    print(456)
                    return True
            return False # lets the event continue to the edit
        return False

    def setDirty(self):
        '''On change of text in textEdit window, set the flag
        "dirty" to True'''
        index = self.tabWidget.currentIndex()
        if index is not 0:
            return
        if self.dirty:
            return True
        self.dirty = True
        self.updateStatus('self.dirty set to True')

    def clearDirty(self):
        'Clear dirty flag'
        self.dirty = False

    def fileNew(self):
        '''Clear both Data Page and Solution Page.'''
        self.plainTextEdit.setPlainText(' ')
        self.plainTextEdit_2.setPlainText(' ')
        self.clearDirty()
        self.filename = None

    def okToContinue(self):
        if self.dirty:
            reply = QMessageBox.question(self,
                    "Data Loader - Unsaved Changes",
                    "Save unsaved changes?",
                    QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                self.clearDirty()
                return self.fileSave()
        return True

    def okRead(self):
        'Pop-up a warning message.'
        reply = QMessageBox.warning(self,
                "Warning",
                '''\nFile Open and Save only in Data Page
\n\(Use SaveAs for the Assembly log)''', QMessageBox.Ok)
        return True

    def fileOpen(self):
        '''Open a file in Data Page (with index == 0)'''
        if self.tabWidget.currentIndex():
            self.okRead()
            return
        if not self.okToContinue():
            return
        dir_ = (os.path.dirname(str(self.filename)) if self.filename is not None else ".")
        filetuple = QFileDialog.getOpenFileName(self,"Open File", dir_,)
        self.filename = filetuple[0]
        #  QFileDialog returns a tuple x with x[0] = file name and
        #  x[1] = type of filter.
        if self.filename:
            self.loadFile(self.filename)
            self.updateStatus('New file opened.')

    def loadFile(self, fname=None):
        fl = open(fname, "r")
        text = fl.read()
        self.plainTextEdit.setPlainText(text)
        self.dirty = False

    def fileSave(self):
        '''Save file with current file name.'''
        if self.tabWidget.currentIndex():
            self.okRead()
            return
        if self.filename is None:
            return self.fileSaveAs()
        else:
            flname = self.filename
            if flname:
                tempText = self.plainTextEdit.toPlainText()
                with open(flname, 'w') as fl: fl.write(tempText)
                self.dirty = False
                self.updateStatus('File saved.')
                return True
            else:
                self.updateStatus('Failed to save... ')
                return False
        self.filename = None
        self.dirty = False

    def fileSaveAs(self):
        '''Save file with a new name.'''
        qpr = self.qprintline
        fname = self.filename or "NoName.txt"
        self.filename = str(QFileDialog.getSaveFileName(self,"ypkpathway - Save File", fname))
        flname = self.filename or "NoName.txt"
        self.filename = flname
        fl = open(flname, 'w')
        tempText = str(self.plainTextEdit.toPlainText())
        fl.write(tempText)
        fl.close()
        self.dirty = False
        self.updateStatus('File saved.')


    def solveAssembly(self):
        printline = self.qprintline
        self.plainTextEdit_2.clear()
        self.tabWidget.setCurrentIndex(1)
        flbase = os.path.basename(str(self.filename))

        title = 'Assembly log for ' + flbase

        printline('='*len(title))
        printline(title)
        printline('='*len(title))


        #print(type(self.plainTextEdit.toPlainText()))
        #qstringobj = self.plainTextEdit.toPlainText().encode('utf-8')
        #print(type(qstringobj)) #<class 'PyQt4.QtCore.QString'>
        #print(qstringobj.toUtf8()[3268:3279])
        #print(str(qstringobj.toUtf8()[3268:3279]))
        #print(type(rawtext), "rawtext")
        #codec0 = .QTextCodec.codecForName("UTF-16");
        #rawtext = unicode(codec0.fromUnicode(tmp), 'UTF-16')
        #unicode(qstringobj.toUtf8(), encoding="UTF-8").decode()
        
        qstringobj = self.plainTextEdit.toPlainText()

        #import sys;sys.exit(42)

        pth = parse( qstringobj )
        
        #import sys;sys.exit(42)

        if len(pth)==0:
            printline("No of sequences found in Data window")
            return

        if self.filename is None:
            self.fileSaveAs()

        dir_, ext = os.path.splitext( str(self.filename))

        fl, log = ypkpathway.pathway( pth, dir_, pYPKa_A = not self.checkbox.isChecked(), print = printline)

        if not fl:
            return

        with open(os.path.join(dir_, "log.txt"),"w") as f: f.write(log)

        shutil.copy2( str(self.filename), os.path.join(dir_, "INDATA_"+os.path.basename(str(self.filename))))

        printline('')
        printline('\n\nAssembly finished.')
        printline('click on the Open pathway button above to open the pathway in the default web browser')
        self.nb =  fl.path

    def qprintline(self, line):
        '''Append one line to Solution Page.'''
        self.plainTextEdit_2.appendPlainText(line.rstrip()) #.decode("utf8"))
        QApplication.processEvents()

    def openNB(self):
        if self.nb:
            subprocess.Popen(["ipython", "notebook", self.nb])



    def aboutBox(self):

        from PyQt5.QtCore import QT_VERSION_STR
        from PyQt5.Qt import PYQT_VERSION_STR
        from sip import SIP_VERSION_STR
        from ._version import get_versions
        __version__ = get_versions()["version"][:5]
        del get_versions
        from IPython import __version__ as IPython_version

        QMessageBox.about(self, "About ypkpathway",
                             """<b>Planning of yeast pathway kit constructions.</b>
                                <p>version: {}<br>
                                 Copyright 2015-2017 Björn Johansson.
                                 This software is released under a BSD style license.
                                 This software comes with no warranties
                                 expressed or implied.<br><br>
                                 Python version: {}<br><br>
                                 IPython version: {}<br>
                                 Qt version: {}<br>
                                 SIP version: {}<br>
                                 PyQt version: {}<br>
                                 pydna version: {}<br></p>
                                 """.format(__version__,
                                            sys.version,
                                            IPython_version,
                                            QT_VERSION_STR,
                                            SIP_VERSION_STR,
                                            PYQT_VERSION_STR,
                                            pydna.__version__[:5]))




    def displayCCPL(self):
        '''Read and display CCPL licence.'''
        self.plainTextEdit.setPlainText(open('CCPL.txt').read())
        self.dirty = False
        self.filename = 'COPYING.txt'
        self.updateStatus('CCPL displayed.')

    def help(self):
        '''Read and display a help file- currently the README.txt.'''
        self.plainTextEdit.setPlainText(open('README.md').read())
        self.dirty = False
        self.filename = 'README.txt'
        self.updateStatus('README displayed.')

    def addActions(self, target, actions):
        '''Actions are added to Tool Bar.'''
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def editAction(self, action, slot=None, shortcut=None, icon=None,
                     tip=None):
        '''This method adds to action: icon, shortcut, ToolTip,\
        StatusTip and can connect triggered action to slot '''
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % (icon)))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            action.triggered.connect(slot)
        return action

    def qreadline(self, lineNo):
        '''Read one line from Data Page (lineNo starts with 0)'''
        return str(self.plainTextEdit.document().\
            findBlockByLineNumber(lineNo).text()).rstrip()

    def updateStatus(self, message):
        '''Keep status current.'''
        if self.filename is not None:
            flbase = os.path.basename(str(self.filename))
            self.setWindowTitle(str("ypkpathway - " +\
                                         flbase + "[*]") )
            self.statusBar().showMessage(message, 5000)
            self.setWindowModified(self.dirty)
예제 #7
0
class RGui(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Main window set up
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle("RGui")

        # File menu
        self.fileMenu = self.menuBar().addMenu('&File')
        self.fileMenu.addAction('&Open', self.openFile,
            Qt.CTRL + Qt.Key_O)
        self.fileMenu.addAction('&Save figure', self.saveFigure,
            Qt.SHIFT + Qt.CTRL + Qt.Key_S)

        # Main widget and its layout
        # subWidget is embedded in the right half of mainWidget
        self.mainWidget = QSplitter(Qt.Horizontal, self)
        self.subWidget = QSplitter(Qt.Vertical, self)

        # Plot canvas set up, added to layout
        self.canvas = CanvasWidget(self,
            width = 10, height = 8, dpi = 100)

        # Set up the control panel
        self.ctrPane = QTabWidget(self)
        self.initCtrPane()

        # List widget embedded in Tab widget
        self.selectPane = QTabWidget(self.subWidget)
        listWidget = QListWidget(self.selectPane)
        listWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.selectPane.addTab(listWidget, 'Untitled')
        self.firstPlot = True
        self.spec = []

        # Set up the layouts
        self.mainWidget.addWidget(self.canvas)
        self.subWidget.addWidget(self.ctrPane)
        self.subWidget.addWidget(self.selectPane)
        self.mainWidget.addWidget(self.subWidget)

        # Set up the MainWindow
        self.mainWidget.setFocus()
        self.setCentralWidget(self.mainWidget)
        self.setGeometry(300, 300, 500, 400)
        self.statusBar()

    def initCtrPane(self):
        # main control set up
        mainCtr = QFrame(self.ctrPane)
        mainCtr.setFrameShape(QFrame.StyledPanel)
        mainCtr.setFrameShadow(QFrame.Sunken)
        # buttons and controls
        backSubButton = QPushButton('Background Subtraction', mainCtr)
        backSubButton.clicked.connect(self.backSub)
        plotButton = QPushButton('Plot', mainCtr)
        plotButton.clicked.connect(self.updatePlot1)
        newTabButton = QPushButton('New tab', mainCtr)
        newTabButton.clicked.connect(self.addTab)
        self.plotPeak = QCheckBox('Plot fitted peak', mainCtr)
        holdPlot = QCheckBox('Hold plot', mainCtr)
        holdPlot.stateChanged.connect(self.canvas.toggleHold)
        # layout
        mainLayout = QGridLayout(mainCtr)
        mainLayout.addWidget(backSubButton, 0, 0)
        mainLayout.addWidget(plotButton, 0, 1)
        mainLayout.addWidget(newTabButton, 1, 0)
        mainLayout.addWidget(self.plotPeak, 2, 0)
        mainLayout.addWidget(holdPlot, 2, 1)
        mainCtr.setLayout(mainLayout)

        self.ctrPane.addTab(mainCtr, 'Main Control')

        # NMF control set up
        NMFCtr = QFrame(self.ctrPane)
        NMFCtr.setFrameShape(QFrame.StyledPanel)
        NMFCtr.setFrameShadow(QFrame.Sunken)
        # input & buttons
        self.alphaBox = MyDoubleBox(NMFCtr)
        self.l1RatioBox = MyDoubleBox(NMFCtr)
        self.loadSettings()
        NMFButton = QPushButton('NMF', NMFCtr)
        NMFButton.clicked.connect(self.NMF)
        # layout
        NMFLayout = QGridLayout(NMFCtr)
        NMFLayout.addWidget(QLabel('α'), 0, 0)
        NMFLayout.addWidget(QLabel('l1 ratio'), 1, 0)
        NMFLayout.addWidget(self.alphaBox, 0, 1)
        NMFLayout.addWidget(self.l1RatioBox, 1, 1)
        NMFLayout.addWidget(NMFButton, 2, 0, 1, 2)

        NMFCtr.setLayout(NMFLayout)

        self.ctrPane.addTab(NMFCtr, 'NMF Control')

    # slots

    def openFile(self):
        fileName = QFileDialog.getOpenFileName(self, "Open file")
        if fileName[0]:
            self.addSpec(fileName[0],
                os.path.basename(fileName[0]))

    def saveFigure(self):
        fileName = QFileDialog.getSaveFileName(self, "Save current figure")
        if fileName[0]:
            self.canvas.saveFigure(fileName)

    def addSpec(self, fileName, title):
        # import spectra from file
        j = self.selectPane.currentIndex()
        l = self.spec[j].nSpec()
        listWidget = self.selectPane.currentWidget()
        self.selectPane.setTabText(j, title)
        self.spec[j].addSpec(fileName, np.array([[0, 0, 0]]))
        for i in range(l + 1, self.spec[j]._coord.shape[0]):
            newItem = QListWidgetItem("[%d %d %d]" % \
                tuple(self.spec[j]._coord[i]), listWidget)
            newItem.setData(Qt.UserRole,
                QVariant([j, i]))
            listWidget.addItem(newItem)
        listWidget.itemDoubleClicked.connect(self.updatePlot2)

    def addTab(self):
        listWidget = QListWidget(self.selectPane)
        listWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.selectPane.addTab(listWidget, 'Untitled')
        self.spec.append(rd.SpecData())

    # defines two update plot slots
    def updatePlot1(self):
        # slot for multiple items
        items = self.selectPane.currentWidget().selectedItems()
        if not items:
            pass # raise error
        bArray = items[0].data(Qt.UserRole)
        n = int(bArray[0])
        use = []
        for item in items:
            bArray = item.data(Qt.UserRole)
            use.append(int(bArray[1]))
        use = np.array(use).reshape(-1)
        self.canvas.updatePlot(self.spec[n], use, self.plotPeak.isChecked())

    def updatePlot2(self, item):
        # slot for a single item
        bArray = item.data(Qt.UserRole)
        n = int(bArray[0])
        i = int(bArray[1])
        use = np.array(i).reshape(-1)
        self.canvas.updatePlot(self.spec[n], use, self.plotPeak.isChecked())

    # Here comes the data analysis operations

    def backSub(self):
        if self.firstPlot:
            pass # raise an error

        fileName = QFileDialog.getOpenFileName(self, "Open background file")
        if fileName[0]:
            bg = rd.SpecData(fileName[0])
            listWidget = self.selectPane.currentWidget()
            item = listWidget.item(0)
            n = item.data(Qt.UserRole)[0]
            newSpec = self.spec[n].backSub(bg.getSpec(0))
            self.addSpec(newSpec, self.currentTabTitle() + '_subtracted')

    def NMF(self):
        if self.firstPlot:
            pass # raise an error

        item = self.selectPane.currentWidget().item(0)
        n = item.data(Qt.UserRole)[0]
        alpha = float(self.alphaBox.text())
        l1Ratio = float(self.l1RatioBox.text())
        model = self.spec[n].NMF(n_components = 3, init = 'nndsvd',
            alpha = alpha, l1_ratio = l1Ratio, sparseness = 'data')
        newSpec = rd.SpecData()
        newSpec._data = np.append(self.spec[n]._data[[0]],
            model.components_, axis = 0)
        newSpec._coord = np.array([[0, 0, 0], [0, 0, 1], [0, 0, 2]])
        newSpec._dim = np.array([1, 1, 3])
        self.addSpec(newSpec, self.currentTabTitle() + '_NMF')

        # save settings
        self.saveSettings()

    def saveSettings(self):
        settings = QSettings(QSettings.UserScope, 'Georgia Tech', 'RamanGui',
            self)
        settings.setValue('alpha', self.alphaBox.text())
        settings.setValue('l1Ratio', self.l1RatioBox.text())

    def loadSettings(self):
        settings = QSettings(QSettings.UserScope, 'Georgia Tech', 'RamanGui',
            self)
        if settings.contains('alpha'):
            self.alphaBox.setText(settings.value('alpha'))
        if settings.contains('l1Ratio'):
            self.l1RatioBox.setText(settings.value('l1Ratio'))

    def currentTabTitle(self):
        return self.selectPane.tabText(self.selectPane.currentIndex())
예제 #8
0
파일: UI.py 프로젝트: Gabrielvth/BrinoPy
class Centro(QWidget):
    def __init__(self, parent=None):
        super(Centro, self).__init__()
        self.widget_abas = None
        self.menu = None
        self.indexer = None
        self.parent = parent
        self.pacotes = dict()
        self.temp_build = mkdtemp('build')
        self.temp_cache = mkdtemp('cache')
        self.log = None
        self.init_ui()

    # noinspection PyUnresolvedReferences
    def init_ui(self):
        # Define grid
        layout = QGridLayout(self)
        layout.setRowStretch(0, 7.5)
        layout.setRowStretch(1, 2.5)
        layout.setColumnMinimumWidth(0, 60)
        layout.setSpacing(5)
        layout.setContentsMargins(0, 0, 0, 0)

        # Cria menu
        self.menu = Menu.Menu(self)
        layout.addWidget(self.menu, 0, 0, 2, 2)

        # Botao para criar nova aba
        btn = QPushButton(self)
        btn.clicked.connect(self.nova_aba)
        btn.setStatusTip("Abrir nova aba")

        # Cria o widget abas
        self.widget_abas = QTabWidget(self.parent)
        self.widget_abas.tabCloseRequested.connect(self.remover_aba)
        self.widget_abas.setTabsClosable(False)
        self.widget_abas.setCornerWidget(btn, Qt.TopRightCorner)
        self.widget_abas.setStyleSheet("background:#252525;")
        layout.addWidget(self.widget_abas, 0, 1, 1, 2)

        # Cria log
        self.log = QPlainTextEdit(self)
        self.log.setStyleSheet(
            "border-radius:5px;background:#101010;margin-bottom:5px;margin-right:5px;"
        )
        self.log.setReadOnly(True)
        self.log.setStatusTip("Log")
        layout.addWidget(self.log, 1, 1, 1, 2)

        # Carrega pacotes de hardware
        self.init_pacotes()
        # Cria menu de placas
        self.criar_menu_placas()
        self.criar_menu_exemplos()

        # Adiciona a aba de boas vindas
        self.widget_abas.addTab(BoasVindas(self), "Bem-Vindo")
        self.show()

    def init_pacotes(self):
        """
        Carrega os pacotes de hardware do Arduino
        :return:
            None
        """
        pasta_hardware = os.path.join('builder', 'hardware')
        self.indexer = IndexadorContribuicao(os.path.join('builder'),
                                             pasta_hardware)
        self.indexer.parse_index()
        self.indexer.sincronizar_com_arquivos()
        self.carregar_hardware(pasta_hardware)
        self.carregar_hardware_contribuido(self.indexer)
        self.carregar_hardware(
            os.path.join(Main.get_caminho_padrao(), 'hardware'))

    def remover_aba(self, index, fechando=False):
        """
        Remove a aba
        :param index:
            Indice da aba
        :param fechando:
            Indica se o programa esta fechando
            default: False
        :return:
            None
        """
        if self.widget_abas.count() > 1 or fechando:
            # Se o index for argumento padrao do sinal (QT)
            if type(index) is not int:
                self.remover_aba(self.widget_abas.currentIndex())
            else:
                arquivo = self.widget_abas.widget(index)
                self.widget_abas.setCurrentIndex(index)
                if not arquivo.salvo:
                    ret = QMessageBox(self)
                    ret.setText(
                        "Gostaria de salvar este código antes de sair?")
                    ret.setIcon(QMessageBox.Question)
                    ret.addButton("Não Salvar", QMessageBox.NoRole)
                    ret.addButton("Cancelar", QMessageBox.RejectRole)
                    ret.addButton("Salvar", QMessageBox.AcceptRole)
                    ret = ret.exec_()
                    if ret == 1:
                        return False
                    elif ret == 2:
                        self.salvar()
                if arquivo is not None:
                    arquivo.deleteLater()
                self.widget_abas.removeTab(index)
        if self.widget_abas.count() == 1:
            self.widget_abas.setTabsClosable(False)

        return True

    def nova_aba(self, path="", salvar_caminho=True):
        """
        Criar nova aba de editor de texto
        :param path:
            Caminho para o arquivo a ser aberto
        :param salvar_caminho:
            Se o caminho deve ser definido como local para salvar
        :return:
            None
        """
        if self.widget_abas.count() == 0 or path:
            editor = EditorDeTexto.CodeEditor(self.widget_abas,
                                              False,
                                              path=path,
                                              salvar_caminho=salvar_caminho)
        else:
            editor = EditorDeTexto.CodeEditor(self.widget_abas,
                                              True,
                                              path=path,
                                              salvar_caminho=salvar_caminho)
        if self.widget_abas.count() == 1:
            self.widget_abas.setTabsClosable(True)
        identificador_aba = editor.get_nome()
        if len(identificador_aba) > 10:
            identificador_aba = identificador_aba[:10] + "..."
        editor.setStyleSheet("background:#252525")
        # Adiciona a aba se o arquivo tiver nome
        if editor.get_nome():
            self.widget_abas.addTab(editor, identificador_aba)
        if editor.get_nome() == "":
            self.remover_aba(self.widget_abas.count() - 1)
        else:
            self.widget_abas.setCurrentIndex(self.widget_abas.count() - 1)
        # Define que nao eh necessario salvar pois acabou de ser aberto
        editor.set_salvo(True)

    def abrir(self, caminho=None, exemplo=True):
        """
        Abrir arquivo .ino ou .brpp em nova aba
        :param caminho:
            endereço para abrir
        :return:
            None
        """
        if caminho is None or not caminho:
            salvar_caminho = True
            dialogo = self.criar_dialogo_arquivo("Abrir arquivo", "Abrir")
            if dialogo.exec_() == QFileDialog.Accepted:
                caminho = dialogo.selectedFiles()[0]
                # Testa se o arquivo existe
                if os.path.exists(caminho):
                    self.nova_aba(caminho, salvar_caminho)
                else:
                    QMessageBox(QMessageBox.Warning, "Erro",
                                "O arquivo não existe", QMessageBox.NoButton,
                                self).show()
        else:
            self.nova_aba(caminho)
            widget = self.widget_abas.widget(self.widget_abas.currentIndex())
            if exemplo:
                widget.caminho = ""

    def salvar(self):
        """
        Salvar arquivo da aba atual
        :return:
            None
        """
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0:
            return
        # Testa se a aba eh a de boas vindas
        editor.set_salvo(True)
        if caminho != "":
            if not os.path.exists(os.path.dirname(caminho)):
                try:
                    os.makedirs(os.path.dirname(caminho))
                except OSError as exc:  # Guard against race condition
                    if exc.errno != exc.errno.EEXIST:
                        raise
            with open(editor.get_caminho(), "w") as arquivo:
                arquivo.write(editor.get_texto())
        else:
            self.salvar_como()

    def salvar_como(self):
        """
        Salvar arquivo atual como
        :return:
            None
        """
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0:
            return
        caminho = editor.get_caminho()
        dialogo = self.criar_dialogo_arquivo('Salvar arquivo', 'Salvar')
        if dialogo.exec_() == QFileDialog.Accepted:
            caminho = dialogo.selectedFiles()[0]
            # Verifica se a pessoa selecionou a pasta ao inves do arquivo em si
            if not ntpath.basename(caminho).__contains__(".brpp"):
                caminho = os.path.join(caminho,
                                       ntpath.basename(caminho) + ".brpp")
            # Troca o identificador da aba
            identificador_aba = ntpath.basename(caminho).replace(".brpp", "")
            if len(identificador_aba) > 10:
                identificador_aba = identificador_aba[:10] + "..."
            self.widget_abas.setTabText(self.widget_abas.currentIndex(),
                                        identificador_aba)
            editor.set_caminho(caminho)
            self.salvar()

    def selecionar_texto(self, cursor, texto, indice_inicial, comprimento):
        """
        Seleciona texto
        :param cursor:
            Cursor do documento
        :param texto:
            Texto a ser selecionado
        :param indice_inicial:
            Ponto de onde comecar a busca
        :param comprimento:
            Tamanho do texto
        :return cursor:
            Cursor com a selecao
        """
        conteudo = self.widget_abas.widget(
            self.widget_abas.currentIndex()).toPlainText()
        indice_comeco = conteudo.find(texto, indice_inicial)
        if indice_comeco == -1:
            indice_comeco = conteudo.find(texto, 0)
        if not indice_comeco == -1:
            cursor.setPosition(indice_comeco, QTextCursor.MoveAnchor)
            cursor.setPosition(indice_comeco + comprimento,
                               QTextCursor.KeepAnchor)
            return cursor
        return -1

    def comentar_linha(self):
        """
        comenta a linha
        :return:
            None
        """
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0:
            return
        cursor_atual = editor.textCursor()
        posicao = cursor_atual.position()
        bloco_atual = cursor_atual.block()
        cursor = QTextCursor(bloco_atual)
        editor.setTextCursor(cursor)
        texto = bloco_atual.text()
        if texto.strip().startswith("//"):
            cursor = self.selecionar_texto(cursor, '/', cursor.position(), 2)
            cursor.removeSelectedText()
            cursor.setPosition(posicao - 2)
            editor.setTextCursor(cursor)
        else:
            editor.insertPlainText('//')
            cursor.setPosition(posicao + 2)
            editor.setTextCursor(cursor)

    def achar(self):
        """
        Achar palavra chave no codigo
        :return:
            None
        """
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0:
            return
        texto, ok = QInputDialog.getText(None, "Buscar", "Achar:")
        if ok and texto != "":
            cursor = editor.textCursor()
            cursor = self.selecionar_texto(cursor, texto, cursor.position(),
                                           len(texto))
            if not cursor == -1:
                editor.setTextCursor(cursor)

    def achar_e_substituir(self):
        """
        Achar e substituir palavras chave por outras
        :return:
            None
        """
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0:
            return
        texto, ok = QInputDialog.getText(None, "Achar", "Achar:")
        subs, ok = QInputDialog.getText(None, "Substituir", "Substituir:")
        if ok and texto != "":
            cursor = editor.textCursor()
            cursor = self.selecionar_texto(cursor, texto, cursor.position(),
                                           len(texto))
            if not cursor == -1:
                cursor.removeSelectedText()
                editor.setTextCursor(cursor)
                editor.insertPlainText(subs)
        return

    @staticmethod
    def criar_dialogo_arquivo(titulo, acao):
        """
        Cria dialogo personalizado para buscar arquivos
        :param titulo:
            Titulo de aba
        :param acao:
            Texto do botao de selecionar
        :return dialogo:
            dialogo
        """
        dialogo = QFileDialog()
        dialogo.setWindowTitle(titulo)
        dialogo.setLabelText(QFileDialog.FileName, "Arquivo:")
        dialogo.setLabelText(QFileDialog.LookIn, "Buscar em:")
        dialogo.setLabelText(QFileDialog.FileType, "Tipo de arquivo:")
        dialogo.setLabelText(QFileDialog.Accept, acao)
        dialogo.setLabelText(QFileDialog.Reject, "Cancelar")
        dialogo.setNameFilters(
            ["Rascunhos Br.ino (*.brpp)", "Rascunhos Arduino (*.ino)"])
        dialogo.selectNameFilter("Rascunhos Br.ino (*.brpp)")
        dialogo.setDirectory(get_caminho_padrao())
        return dialogo

    def abrir_serial(self):
        """
        Abre o monitor serial
        :return:
            None
        """
        self.parent.abrir_serial()

    def carregar_hardware(self, pasta):
        """
        Carrega as opcoes de hardware do Arduino
        :param pasta:
            Diretorio do hardware
        :return:
            None
        """
        if not os.path.isdir(pasta):
            return
        lista = [
            os.path.join(pasta, pasta_) for pasta_ in os.listdir(pasta)
            if os.path.isdir(os.path.join(pasta, pasta_))
        ]
        if len(lista) == 0:
            return
        lista = sorted(lista, key=str.lower)
        lista.remove(os.path.join(pasta, "tools"))
        for item in lista:
            nome_item = os.path.basename(item)
            if nome_item in self.pacotes:
                pacote_alvo = self.pacotes.get(nome_item)
            else:
                pacote_alvo = PacoteAlvo(nome_item)
                self.pacotes[nome_item] = pacote_alvo
            self.carregar_pacote_alvo(pacote_alvo, item)

    def carregar_hardware_contribuido(self, indexer):
        """
        :param indexer:
            Indexador de contribuicoes
        :return:
            None
        """
        for pacote in indexer.criar_pacotes_alvo():
            if self.pacotes.get(pacote.get_id(), False):
                self.pacotes[pacote.get_id()] = pacote

    @staticmethod
    def carregar_pacote_alvo(pacote_alvo, pasta):
        """
        Carrega o pacote alvo
        :param pacote_alvo:
            Pacote de hardware
        :param pasta:
            Diretorio do pacote
        :return:
            None
        """
        pastas = os.listdir(pasta)
        if len(pastas) == 0:
            return
        for item in pastas:
            plataforma_alvo = PlataformaAlvo(item, os.path.join(pasta, item),
                                             pacote_alvo)
            pacote_alvo.get_plataformas()[item] = plataforma_alvo

    def criar_menu_placas(self):
        """
        Cria o menu das placas
        :return:
            None
        """
        self.menus_personalizados = list()
        titulos_menus_personalizados = list()
        for pacote_alvo in self.pacotes.values():
            for plataforma_alvo in pacote_alvo.get_lista_plataformas():
                titulos_menus_personalizados += plataforma_alvo.get_menus(
                ).values()
        for titulo_menu_personalizado in titulos_menus_personalizados:
            menu = QMenu(titulo_menu_personalizado)
            self.menus_personalizados.append(menu)
        placas = QActionGroup(self.parent)
        placas.setExclusive(True)
        for pacote_alvo in self.pacotes.values():
            for plataforma_alvo in pacote_alvo.get_lista_plataformas():
                nome = plataforma_alvo.get_preferencias().get("name")
                self.parent.menu_placas.addAction(QAction(nome, self))
                for placa in plataforma_alvo.get_placas().values():
                    if not placa.get_preferencias().get('hide'):
                        self.parent.menu_placas.addAction(
                            placa.criar_acao(self))

    def criar_menu_portas(self):
        """
        Cria o menu das portas
        :return:
            None
        """
        for acao in self.parent.menu_portas.actions():
            self.parent.menu_portas.removeAction(acao)
        portas = QActionGroup(self.parent)
        portas.setExclusive(True)
        n_portas = len(self.serial_ports())
        if n_portas > 0:
            for porta in self.serial_ports():
                porta_acao = Porta.criar_acao(porta, self)
                self.parent.menu_portas.addAction(porta_acao)
                if n_portas == 1:
                    Preferencias.set('serial.port', porta)
        else:
            self.parent.menu_portas.addAction(
                QAction("Não há portas disponíveis", self))

    def criar_menu_exemplos(self):
        """
        Cria o menu exemplos
        :return:
            None
        """
        caminho_exemplos = os.path.join('recursos', 'exemplos')
        pastas_exemplo = [
            x for x in os.listdir(caminho_exemplos)
            if os.path.isdir(os.path.join(caminho_exemplos, x))
        ]
        pastas_exemplo.sort()
        for pasta_exemplo in pastas_exemplo:
            menu = self.parent.menu_exemplos.addMenu(pasta_exemplo)
            for exemplo in os.listdir(
                    os.path.join(caminho_exemplos, pasta_exemplo)):
                exemplo_acao = QAction(exemplo, self)
                caminho_exemplo = os.path.join(caminho_exemplos, pasta_exemplo,
                                               exemplo, exemplo + ".brpp")
                menu.addAction(exemplo_acao)
                exemplo_acao.triggered.connect(
                    functools.partial(self.abrir, caminho_exemplo, True))

    def on_troca_placa_ou_porta(self):
        """
        Troca a placa
        :return:
            None
        """
        plataforma = self.get_plataforma_alvo()
        pastas_bibliotecas = list()
        # if plataforma:
        # core = self.get_preferencias_placa()
        pasta_plataforma = plataforma.get_pasta()
        pastas_bibliotecas.append(os.path.join(pasta_plataforma, 'libraries'))
        pastas_bibliotecas.append(
            os.path.join(get_caminho_padrao(), 'bibliotecas'))

    def get_preferencias_placa(self):
        """
        Busca as preferencias da palca que esta sendo utilizada
        :return prefs:
            Retorna as preferencias
        """
        placa_alvo = self.get_placa_alvo()
        if placa_alvo is None:
            return None
        id_placa = placa_alvo.get_id()
        prefs = placa_alvo.get_preferencias()
        nome_extendido = prefs.get("name")
        for id_menu in placa_alvo.get_ids_menus():
            if not placa_alvo.tem_menu(id_menu):
                continue
            entrada = Preferencias.get("custom_" + id_menu)
            if entrada is not None and entrada.startswith(id_placa):
                id_selecao = entrada[len(id_placa) + 1:]
                prefs.update(
                    placa_alvo.get_preferencias_menu(id_menu, id_selecao))
                nome_extendido += ", " + placa_alvo.get_label_menu(
                    id_menu, id_selecao)
        prefs['name'] = nome_extendido
        ferramentas = list()
        plataforma = self.indexer.get_plataforma_contribuida(
            self.get_plataforma_alvo())
        if plataforma is not None:
            ferramentas.extend(plataforma.get_ferramentas_resolvidas())

        core = prefs.get("build.core")
        if core is not None and core.__contains__(":"):
            separado = core.split(":")
            referenciada = self.get_plataforma_atual_do_pacote(separado[0])
            if referenciada is not None:
                plat_referenciada = self.indexer.get_plataforma_contribuida(
                    referenciada)
                ferramentas.extend(
                    plat_referenciada.get_ferramentas_resolvidas())
        prefix = "runtime.tools."
        for tool in ferramentas:
            pasta = tool.get_pasta_instalada()
            caminho = os.path.abspath(pasta)
            prefs[(prefix + tool.get_nome() + ".path")] = caminho
            Preferencias.set(prefix + tool.get_nome() + ".path", caminho)
            Preferencias.set(
                prefix + tool.get_nome() + "-" + tool.get_versao() + ".path",
                caminho)
        return prefs

    def get_placa_alvo(self):
        """
        Busca a placa alvo
        :return
            placa alvo:
        """
        plataforma_alvo = self.get_plataforma_alvo()
        if plataforma_alvo:
            placa = Preferencias.get('board')
            return plataforma_alvo.get_placa(placa)

    def get_plataforma_alvo(self, pacote=None, plataforma=None):
        """
        Pega a plataforma alvo
        :param pacote:
            Pacote da plataforma
        :param plataforma:
            A plataforma
        :return plataforma_alvo:
            Plataforma alvo
        """
        if pacote is None:
            pacote = Preferencias.get('target_package')
        if plataforma is None:
            plataforma = Preferencias.get('target_platform')
        p = self.pacotes.get(pacote)
        plataforma_alvo = p.get(plataforma)
        return plataforma_alvo

    def get_plataforma_atual_do_pacote(self, pacote):
        """
        :param pacote:
            Pacote da plataforma
        :return:
            Retorna a plataforma alvo
        """
        return self.get_plataforma_alvo(pacote,
                                        Preferencias.get("target_platform"))

    def compilar(self):
        """
        Compila o codigo da aba atual
        :return:
            None
        """
        self.salvar()
        self.log.clear()
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0 or caminho == '':
            return None
        placa_alvo = self.get_placa_alvo()
        plataforma_alvo = placa_alvo.get_plataforma()
        pacote_alvo = plataforma_alvo.get_pacote()
        # Transforma o codigo brpp em ino
        traduzir(caminho)
        resultado = compilar_arduino_builder(caminho, placa_alvo,
                                             plataforma_alvo, pacote_alvo,
                                             self.temp_build, self.temp_cache)
        self.log.insertPlainText(str(resultado, sys.stdout.encoding))

    def upload(self):
        """
        Compila e carrega o codigo da aba atual
        :return:
            None
        """
        self.compilar()
        editor = self.widget_abas.widget(self.widget_abas.currentIndex())
        caminho = editor.get_caminho()
        # Testa se a aba eh a de boas vindas
        if caminho == 0 or caminho == '':
            return None
        caminho = editor.get_caminho()
        # Ajustes do Arduino
        # TODO Terminar ajustes
        caminho_temp = self.temp_build
        uploader = None
        if uploader is None:
            uploader = Uploader.get_uploader_por_preferencias()
            uploader = Uploader.UploaderSerial(False)
        sucesso = False
        nome = os.path.basename(caminho).replace("brpp", "ino")
        sucesso = uploader.upload_usando_preferencias(self, caminho_temp,
                                                      os.path.basename(nome))

    @staticmethod
    def serial_ports():
        """
        Lista as portas seriais disponiveis
        :raises EnvironmentError:
            Plataforma desconhecida ou nao suportada
        :returns:
            Lista das portas seriais disponiveis
        """
        if sys.platform.startswith('win'):
            ports = ['COM%s' % (i + 1) for i in range(256)]
        elif sys.platform.startswith('linux') or sys.platform.startswith(
                'cygwin'):
            # this excludes your current terminal "/dev/tty"
            ports = glob.glob('/dev/tty[A-Za-z]*')
        elif sys.platform.startswith('darwin'):
            ports = glob.glob('/dev/tty.*')
        else:
            raise EnvironmentError('Unsupported platform')

        result = []
        for port in ports:
            try:
                s = serial.Serial(port)
                s.close()
                result.append(port)
            except (OSError, serial.SerialException):
                pass
        return result

    def get_menu_personalizado_placa(self, title):
        for menu in self.menus_personalizados:
            if menu.title() == title:
                return menu

    def instalar_biblioteca(self):
        caminho_bibliotecas = os.path.join(get_caminho_padrao(), "bibliotecas")
        dialogo = QFileDialog()
        dialogo.setWindowTitle("Escolher biblioteca")
        dialogo.setLabelText(QFileDialog.FileName, "Arquivo:")
        dialogo.setLabelText(QFileDialog.LookIn, "Buscar em:")
        dialogo.setLabelText(QFileDialog.FileType, "Tipo de arquivo:")
        dialogo.setLabelText(QFileDialog.Accept, "Escolher")
        dialogo.setLabelText(QFileDialog.Reject, "Cancelar")
        dialogo.setFileMode(QFileDialog.DirectoryOnly)
        dialogo.setDirectory(get_caminho_padrao())
        if dialogo.exec_() == QFileDialog.Accepted:
            caminho = dialogo.selectedUrls()[0].path()
            if (caminho.startswith("/") and os.name == 'nt'):
                caminho = caminho[1:]
            # Testa se o arquivo existe
            if os.path.exists(caminho):
                try:
                    shutil.copytree(
                        caminho,
                        os.path.join(caminho_bibliotecas,
                                     os.path.basename(caminho)))
                    # Directories are the same
                except shutil.Error as e:
                    print('Directory not copied. Error: %s' % e)
                    # Any error saying that the directory doesn't exist
                except OSError as e:
                    print('Directory not copied. Error: %s' % e)
            else:
                QMessageBox(QMessageBox.Warning, "Erro",
                            "O arquivo não existe", QMessageBox.NoButton,
                            self).show()
        else:
            return
예제 #9
0
class Labor_Tabs(QWidget):
    '''Used to create the labor tabs on the main template
    '''
    previous_row = int
    labor_total = pyqtSignal(float)

    def __init__(self, job_number):
        super().__init__()
        self.init()
        self.setWindowTitle('BEI Invoice Number {}'.format(job_number))

    def init(self):
        '''Calls the initialization of the labor tabs
        '''
        self.labor()
        #        self.addTab(self.labor_tab,'Labor Entry')
        self.previous_row = int
        self.maximum_row = 0

    def labor(self):
        '''Widget for the labor tabs

            How it will work:
                1.) Open 'Changable_Documents/Labor_Rates.csv'
                2.) Read the document in and get the names out of it
                3.) Create a dictionary with the names tied to an 
                    instantiation of the tabs_technicain
                4.) Go through and add set the layouts up 
        '''
        #get the current working directory and navigate to the correct folder
        directory = str(
            Path(
                os.path.join(
                    os.path.join(os.environ['USERPROFILE'], 'BEI_Invoices')),
                'Basic_Information_Totals'))
        tech_data = open(str(Path(os.path.join(directory, 'Labor_Rates.csv'))),
                         'r')
        information = tech_data.readlines()
        tech_data.close()
        self.hourly_wage = {}
        tech_names = []
        for i in range(len(information)):
            tech_names.append(information[i].split(sep=',')[0])
            self.hourly_wage[i] = [
                float(information[i].split(sep=',')[1]),
                float(information[i].split(sep=',')[2])
            ]

        self.technicians = QTabWidget(self)
        #set up the tab for each technician
        self.t0 = Labor_Setup().labor_table
        self.t1 = Labor_Setup().labor_table
        self.t2 = Labor_Setup().labor_table
        self.t3 = Labor_Setup().labor_table
        self.t4 = Labor_Setup().labor_table
        self.t5 = Labor_Setup().labor_table
        self.t6 = Labor_Setup().labor_table
        self.t7 = Labor_Setup().labor_table
        self.t_tabs = [
            self.t0, self.t1, self.t2, self.t3, self.t4, self.t5, self.t6,
            self.t7
        ]
        for i in range(len(tech_names)):
            self.technicians.addTab(self.t_tabs[i], tech_names[i])
        for j in range(len(tech_names), len(self.t_tabs)):
            self.t_tabs[j].close()


#        self.technicians.addTab(self.t1,'David')
#        self.technicians.addTab(self.t2,'Alan')
#        self.technicians.addTab(self.t3,'Hanna')

        self.counts = self.technicians.count()

        self.total_layout = QVBoxLayout()
        self.total_layout.addWidget(self.technicians)
        self.setLayout(self.total_layout)

    def keyPressEvent(self, event):
        key = event.key()
        operator = self.t0
        if key == Qt.Key_Return or key == Qt.Key_Enter:
            try:
                index = self.technicians.currentIndex()
                operator = self.determine_tech(index)

                for cqt in operator.tableWidget.selectedItems():
                    current_row = cqt.row()
    #            if current_row!=self.previous_row:
                operator.tableWidget.setCurrentCell(current_row + 1, 0)
                self.calculate(current_row, operator, index)

    #            self.previous_row=current_row
            except:
                pass
        else:
            super(Labor_Tabs, self).keyPressEvent(event)

    def calculate(self, row, current_tech, index):
        '''Calculate the overtime and regular time for the current row
        '''
        try:
            regular_hours = float(current_tech.tableWidget.item(row, 3).text())
        except:
            regular_hours = 0
        try:
            ot_hours = float(current_tech.tableWidget.item(row, 4).text())
        except:
            ot_hours = 0
        try:
            hours_wage = float(current_tech.tableWidget.item(row, 5).text())
        except:
            hours_wage = self.hourly_wage[index][0]
        try:
            ot_hours_wage = float(current_tech.tableWidget.item(row, 6).text())
        except:
            ot_hours_wage = self.hourly_wage[index][1]
        labor_t = regular_hours * hours_wage + ot_hours * ot_hours_wage
        current_tech.tableWidget.setItem(row, 7,
                                         QTableWidgetItem(str(labor_t)))
        total = self.find_tech_total(index)
        self.labor_total.emit(total)

    def find_tech_total(self, index):
        '''Sum up the total amount for the specified tech
        '''
        operator = self.determine_tech(index)
        total = 0
        for i in range(100):
            try:
                total += float(operator.tableWidget.item(i, 7).text())
            except:
                break
        return total

    def find_tech_individual(self):
        '''
        Find the individual tech labor contribution
        '''
        totals = []
        for i in range(self.counts):
            totals.append(self.find_tech_total(i))
        return totals

    def read_data_out(self, index):
        operator = self.determine_tech(index)

        labor_data = []
        for i in range(100):
            try:
                row = []
                for j in range(8):
                    try:
                        float(operator.tableWidget.item(i, 7).text())
                        if j == 2:
                            row.append(
                                operator.tableWidget.item(i, j).text().replace(
                                    ',', '.'))
                        else:
                            row.append(operator.tableWidget.item(i, j).text())
                    except:
                        row.append('')
                labor_data.append(row)
            except:
                break
        return labor_data

    def read_in_data(self, index, data):
        operator = self.determine_tech(index)

        for i in range(len(data)):
            for j in range(len(data[i])):
                if data[i][j] != '':
                    operator.tableWidget.setItem(i, j,
                                                 QTableWidgetItem(data[i][j]))

    def determine_tech(self, index):
        operator = self.t_tabs[index]
        #        if index==0:
        #            operator=self.t0
        #        elif index==1:
        #            operator=self.t1
        #        elif index==2:
        #            operator=self.t2
        #        elif index==3:
        #            operator=self.t3
        return operator
예제 #10
0
class SetupDialog(QDialog):
    """ This dialog consists of two parts/tabs: The first one is supposed to help choosing
        container, device name and mount point to unlock an existing container.
        The second tab assists in creating a new encrypted LUKS container.
    """
    def __init__(self, parent):
        """ :param parent: The parent window/dialog used to enable modal behaviour
            :type parent: :class:`PyQt4.QtGui.QWidget`
        """
        super(SetupDialog,
              self).__init__(parent,
                             Qt.WindowCloseButtonHint | Qt.WindowTitleHint)
        self.setWindowTitle(_('luckyLUKS'))

        self.worker = parent.worker
        self.is_busy = False

        # build ui
        self.layout = QVBoxLayout()
        self.layout.setSizeConstraint(QLayout.SetFixedSize)
        style = QApplication.style()
        # set up stacked layout: initially only the main tab pane (unlock/create)
        self.main_pane = QStackedWidget()
        self.tab_pane = QTabWidget()
        self.main_pane.addWidget(self.tab_pane)
        self.layout.addWidget(self.main_pane)
        self.create_pane = None  # init in on_create_container()

        # Unlock Tab
        unlock_grid = QGridLayout()
        unlock_grid.setColumnMinimumWidth(1, 220)
        uheader = QLabel(
            _('<b>Unlock an encrypted container</b>\n') +
            _('Please select container file and name'))
        uheader.setContentsMargins(0, 10, 0, 10)
        unlock_grid.addWidget(uheader, 0, 0, 1, 3, Qt.AlignCenter)

        label = QLabel(_('container file'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 1, 0)
        self.unlock_container_file = QLineEdit()
        unlock_grid.addWidget(self.unlock_container_file, 1, 1)
        button_choose_file = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '', self)
        button_choose_file.setToolTip(_('choose file'))
        unlock_grid.addWidget(button_choose_file, 1, 2)
        button_choose_file.clicked.connect(self.on_select_container_clicked)

        label = QLabel(_('device name'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 2, 0)
        self.unlock_device_name = QLineEdit()
        unlock_grid.addWidget(self.unlock_device_name, 2, 1)
        # advanced settings
        a_settings = QExpander(_('Advanced'), self, False)
        unlock_grid.addWidget(a_settings, 3, 0, 1, 3)

        label = QLabel(_('key file'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 4, 0)
        self.unlock_keyfile = QLineEdit()
        unlock_grid.addWidget(self.unlock_keyfile, 4, 1)
        button_choose_uKeyfile = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_uKeyfile.setToolTip(_('choose keyfile'))
        unlock_grid.addWidget(button_choose_uKeyfile, 4, 2)
        button_choose_uKeyfile.clicked.connect(
            lambda: self.on_select_keyfile_clicked('Unlock'))
        a_settings.addWidgets([
            unlock_grid.itemAtPosition(4, column).widget()
            for column in range(0, 3)
        ])

        label = QLabel(_('mount point'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 5, 0)
        self.unlock_mountpoint = QLineEdit()
        unlock_grid.addWidget(self.unlock_mountpoint, 5, 1)
        button_choose_mountpoint = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_mountpoint.setToolTip(_('choose folder'))
        unlock_grid.addWidget(button_choose_mountpoint, 5, 2)
        button_choose_mountpoint.clicked.connect(
            self.on_select_mountpoint_clicked)
        a_settings.addWidgets([
            unlock_grid.itemAtPosition(5, column).widget()
            for column in range(0, 3)
        ])

        unlock_grid.setRowStretch(6, 1)
        unlock_grid.setRowMinimumHeight(6, 10)
        button_help_unlock = QPushButton(
            style.standardIcon(QStyle.SP_DialogHelpButton), _('Help'))
        button_help_unlock.clicked.connect(self.show_help_unlock)
        unlock_grid.addWidget(button_help_unlock, 7, 2)

        unlock_tab = QWidget()
        unlock_tab.setLayout(unlock_grid)
        self.tab_pane.addTab(unlock_tab, _('Unlock Container'))

        # Create Tab
        create_grid = QGridLayout()
        cheader = QLabel(
            _('<b>Create a new encrypted container</b>\n') +
            _('Please choose container file, name and size'))
        cheader.setContentsMargins(0, 10, 0, 10)
        create_grid.addWidget(cheader, 0, 0, 1, 3, Qt.AlignCenter)

        label = QLabel(_('container file'))
        label.setIndent(5)
        create_grid.addWidget(label, 1, 0)
        self.create_container_file = QLineEdit()
        create_grid.addWidget(self.create_container_file, 1, 1)
        button_choose_file = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_file.setToolTip(_('set file'))
        create_grid.addWidget(button_choose_file, 1, 2)
        button_choose_file.clicked.connect(self.on_save_container_clicked)

        label = QLabel(_('device name'))
        label.setIndent(5)
        create_grid.addWidget(label, 2, 0)
        self.create_device_name = QLineEdit()
        create_grid.addWidget(self.create_device_name, 2, 1)

        label = QLabel(_('container size'))
        label.setIndent(5)
        create_grid.addWidget(label, 3, 0)
        self.create_container_size = QSpinBox()
        self.create_container_size.setRange(1, 1000000000)
        self.create_container_size.setValue(1)
        create_grid.addWidget(self.create_container_size, 3, 1)

        self.create_size_unit = QComboBox()
        self.create_size_unit.addItems(['MB', 'GB'])
        self.create_size_unit.setCurrentIndex(1)
        create_grid.addWidget(self.create_size_unit, 3, 2)
        # advanced settings
        a_settings = QExpander(_('Advanced'), self, False)
        create_grid.addWidget(a_settings, 4, 0, 1, 3)

        label = QLabel(_('key file'))
        label.setIndent(5)
        create_grid.addWidget(label, 5, 0)
        self.create_keyfile = QLineEdit()
        create_grid.addWidget(self.create_keyfile, 5, 1)
        button_choose_cKeyfile = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_cKeyfile.setToolTip(_('choose keyfile'))
        create_grid.addWidget(button_choose_cKeyfile, 5, 2)
        button_choose_cKeyfile.clicked.connect(
            lambda: self.on_select_keyfile_clicked('Create'))
        a_settings.addWidgets([
            create_grid.itemAtPosition(5, column).widget()
            for column in range(0, 3)
        ])

        button_create_keyfile = QPushButton(_('Create key file'))
        button_create_keyfile.clicked.connect(self.on_create_keyfile)
        create_grid.addWidget(button_create_keyfile, 6, 1)
        a_settings.addWidgets([button_create_keyfile])

        label = QLabel(_('format'))
        label.setIndent(5)
        create_grid.addWidget(label, 7, 0)
        self.create_encryption_format = QComboBox()
        self.create_encryption_format.addItem('LUKS')
        self.create_encryption_format.addItem('TrueCrypt')
        if not is_installed('tcplay'):
            self.create_encryption_format.setEnabled(False)
        self.create_encryption_format.setCurrentIndex(0)
        create_grid.addWidget(self.create_encryption_format, 7, 1)
        a_settings.addWidgets([
            create_grid.itemAtPosition(7, column).widget()
            for column in range(0, 2)
        ])

        label = QLabel(_('filesystem'))
        label.setIndent(5)
        create_grid.addWidget(label, 8, 0)
        filesystems = ['ext4', 'ext2', 'ntfs']
        self.create_filesystem_type = QComboBox()
        for filesystem in filesystems:
            if is_installed('mkfs.' + filesystem):
                self.create_filesystem_type.addItem(filesystem)
        self.create_filesystem_type.setCurrentIndex(0)
        create_grid.addWidget(self.create_filesystem_type, 8, 1)
        a_settings.addWidgets([
            create_grid.itemAtPosition(8, column).widget()
            for column in range(0, 2)
        ])

        create_grid.setRowStretch(9, 1)
        create_grid.setRowMinimumHeight(9, 10)
        button_help_create = QPushButton(
            style.standardIcon(QStyle.SP_DialogHelpButton), _('Help'))
        button_help_create.clicked.connect(self.show_help_create)
        create_grid.addWidget(button_help_create, 10, 2)

        create_tab = QWidget()
        create_tab.setLayout(create_grid)
        self.tab_pane.addTab(create_tab, _('Create New Container'))
        self.tab_pane.currentChanged.connect(self.on_switchpage_event)

        # OK and Cancel buttons
        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel,
                                        parent=self)
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))
        self.buttons.accepted.connect(self.on_accepted)
        self.buttons.rejected.connect(self.reject)
        self.layout.addWidget(self.buttons)

        # ui built, add to widget
        self.setLayout(self.layout)

    def on_create_container(self):
        """ Triggered by clicking create.
            Hides the unlock/create pane and switches to a status pane
            where the progress in creating the new container can be followed step by step.
            This shows the header and the first step:
            Initializing the container file with random data
        """
        self.init_create_pane()

        header = QLabel(
            _('<b>Creating new container</b>\n') +
            _('patience .. this might take a while'))
        header.setContentsMargins(0, 10, 0, 10)
        self.create_status_grid.addWidget(header, 0, 0, 1, 3, Qt.AlignCenter)

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 1/3</b>'), 1, 0)
        self.create_status_grid.addWidget(
            QLabel(_('Initializing Container File')), 1, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[0].setRange(0, 100)
        self.create_status_grid.addWidget(self.create_progressbars[0], 2, 0, 1,
                                          3)
        self.create_status_grid.setRowStretch(7, 1)  # top align
        # add to stack widget and switch display
        self.main_pane.addWidget(self.create_pane)
        self.main_pane.setCurrentIndex(1)

        # calculate designated container size for worker and progress indicator
        size = self.create_container_size.value()
        size = size * (
            1024 * 1024 * 1024 if self.create_size_unit.currentIndex() == 1
            else 1024 * 1024)  # GB vs MB
        location = self.encode_qt_output(self.create_container_file.text())
        if not os.path.dirname(location):
            location = os.path.join(os.path.expanduser('~'), location)
            self.create_container_file.setText(location)
        # start timer for progressbar updates during container creation
        self.create_timer.timeout.connect(
            lambda: self.display_progress_percent(location, size))
        self.create_timer.start(500)

        self.worker.execute(command={
            'type':
            'request',
            'msg':
            'create',
            'device_name':
            self.encode_qt_output(self.create_device_name.text()),
            'container_path':
            location,
            'container_size':
            size,
            'key_file':
            self.encode_qt_output(self.create_keyfile.text())
            if self.create_keyfile.text() != '' else None,
            'filesystem_type':
            str(self.create_filesystem_type.currentText()),
            'encryption_format':
            str(self.create_encryption_format.currentText()),
        },
                            success_callback=self.on_luksFormat_prompt,
                            error_callback=lambda msg: self.
                            display_create_failed(msg, stop_timer=True))

    def on_luksFormat_prompt(self, msg):
        """ Triggered after the container file is created on disk
            Shows information about the next step and asks the user
            for the passphrase to be used with the new container
        """
        self.set_progress_done(self.create_timer, self.create_progressbars[0])

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 2/3</b>'), 3, 0)
        self.create_status_grid.addWidget(QLabel(_('Initializing Encryption')),
                                          3, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[1].setRange(0, 0)
        self.create_status_grid.addWidget(self.create_progressbars[1], 4, 0, 1,
                                          3)

        if msg == 'getPassword':
            try:
                self.worker.execute(
                    command={
                        'type': 'response',
                        'msg': FormatContainerDialog(self).get_password()
                    },
                    success_callback=self.on_creating_filesystem,
                    error_callback=self.display_create_failed)
            except UserInputError:  # user cancelled dlg
                self.worker.execute({
                    'type': 'abort',
                    'msg': ''
                }, None, None)  # notify worker process
                self.display_create_failed(_('Initialize container aborted'))
        else:  # using keyfile
            self.worker.execute(command={
                'type': 'response',
                'msg': ''
            },
                                success_callback=self.on_creating_filesystem,
                                error_callback=self.display_create_failed)

    def on_creating_filesystem(self, msg):
        """ Triggered after LUKS encryption got initialized.
            Shows information about the last step
        """
        self.set_progress_done(progressbar=self.create_progressbars[1])

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 3/3</b>'), 5, 0)
        self.create_status_grid.addWidget(QLabel(_('Initializing Filesystem')),
                                          5, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[2].setRange(0, 0)
        self.create_status_grid.addWidget(self.create_progressbars[2], 6, 0, 1,
                                          3)

        self.worker.execute(command={
            'type': 'response',
            'msg': ''
        },
                            success_callback=self.display_create_success,
                            error_callback=self.display_create_failed)

    def display_create_success(self, msg):
        """ Triggered after successful creation of a new container """
        self.set_progress_done(progressbar=self.create_progressbars[2])
        # copy values of newly created container to unlock dlg und reset create values
        self.unlock_container_file.setText(self.create_container_file.text())
        self.unlock_device_name.setText(self.create_device_name.text())
        self.unlock_keyfile.setText(self.create_keyfile.text())
        show_info(
            self,
            _('<b>{device_name}\nsuccessfully created!</b>\nClick on unlock to use the new container'
              ).format(device_name=self.encode_qt_output(
                  self.create_device_name.text())), _('Success'))
        # reset create ui and switch to unlock tab
        self.create_container_file.setText('')
        self.create_device_name.setText('')
        self.create_container_size.setValue(1)
        self.create_size_unit.setCurrentIndex(1)
        self.create_keyfile.setText('')
        self.create_encryption_format.setCurrentIndex(0)
        self.create_filesystem_type.setCurrentIndex(0)
        self.display_create_done()
        self.tab_pane.setCurrentIndex(0)

    def display_create_failed(self, errormessage, stop_timer=False):
        """ Triggered when an error happend during the create process
            :param errormessage: errormessage to be shown
            :type errormessage: str
            :param stop_timer: stop a progress indicator?
            :type stop_timer: bool
        """
        if stop_timer:
            self.set_progress_done(self.create_timer)
        show_alert(self, errormessage)
        self.display_create_done()

    def display_create_done(self):
        """ Helper to hide the create process informations and show the unlock/create pane """
        self.is_busy = False
        self.main_pane.setCurrentIndex(0)
        self.buttons.setEnabled(True)

    def set_progress_done(self, timeout=None, progressbar=None):
        """ Helper to end stop the progress indicator
            :param timeout: Timer to stop
            :type timeout: QTimer or None
            :param progressbar: progressbar widget to set to 'Done'
            :type progressbar: :class:`QProgressBar` or None
        """
        if timeout is not None:
            timeout.stop()
        if progressbar is not None:
            if not progressbar.maximum():
                progressbar.setRange(0, 100)
            progressbar.setValue(100)
            progressbar.setFormat(_('Done'))

    def on_accepted(self):
        """ Event handler for response:
            Start unlock or create action
        """
        try:
            if self.tab_pane.currentIndex() == 1:

                self.on_create_container()

            else:
                UnlockContainerDialog(
                    self, self.worker, self.get_luks_device_name(),
                    self.get_encrypted_container(), self.get_keyfile(),
                    self.get_mount_point()).communicate()  # blocks

                # optionally create startmenu entry
                self.show_create_startmenu_entry()
                # all good, now switch to main window
                self.accept()

        except UserInputError as error:
            show_alert(self, format_exception(error))

    def init_create_pane(self):
        """ Helper that initializes the ui for the progress indicators shown while creating containers or keyfiles """
        self.is_busy = True
        self.create_progressbars = []
        self.create_timer = QTimer(self)

        self.buttons.setEnabled(False)

        if self.main_pane.count() > 1:  # remove previous create display if any
            self.main_pane.removeWidget(self.create_pane)

        # built ui
        self.create_pane = QWidget()
        self.create_status_grid = QGridLayout()
        self.create_pane.setLayout(self.create_status_grid)
        self.create_status_grid.setVerticalSpacing(5)

    def on_create_keyfile(self):
        """ Triggered by clicking the `create key file` button below the key file text field (create)
            Asks for key file location if not already provided, creates the progress ui and starts a create-thread
        """
        if self.create_keyfile.text() == '':
            key_file = self.encode_qt_output(
                self.on_save_file(_('new_keyfile.bin')))
        else:
            key_file = self.encode_qt_output(self.create_keyfile.text())

        if not os.path.dirname(key_file):
            key_file = os.path.join(os.path.expanduser('~'), key_file)

        self.init_create_pane()

        header = QLabel(_('<b>Creating key file</b>'))
        self.create_status_grid.addWidget(header, 1, 0, 1, 3, Qt.AlignCenter)
        header.setContentsMargins(0, 30, 0, 10)

        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[0].setRange(0, 100)
        self.create_status_grid.addWidget(self.create_progressbars[0], 2, 0, 1,
                                          3)
        info = QLabel(
            _('This might take a while. Since computers are deterministic machines\n'
              'it is quite a challenge to generate real random data for the key.\n'
              '\n'
              'You can speed up the process by typing, moving the mouse\n'
              'and generally use the computer while the key gets generated.'))
        info.setContentsMargins(0, 10, 0, 10)
        self.create_status_grid.addWidget(info, 3, 0, 1, 3, Qt.AlignCenter)

        self.create_status_grid.setRowStretch(4, 2)  # vertical align
        # add to stack widget and switch display
        self.main_pane.addWidget(self.create_pane)
        self.main_pane.setCurrentIndex(1)

        # start timer for progressbar updates during keyfile creation
        self.create_timer.timeout.connect(
            lambda: self.display_progress_percent(key_file, 1024))
        self.create_timer.start(500)

        # run QThread with keyfile creation
        from luckyLUKS.utils import KeyfileCreator

        self.create_thread = KeyfileCreator(self, key_file)
        self.create_thread.start()

    def on_keyfile_created(self, key_file_path):
        """ Triggered when key file creation was successful. Restores the normal setup ui """
        self.set_progress_done(self.create_timer,
                               progressbar=self.create_progressbars[0])
        show_info(
            self,
            _('<b>{key_file}\nsuccessfully created!</b>\n'
              'You can use this key file now,\n'
              'to create a new container.').format(key_file=key_file_path),
            _('Success'))
        self.display_create_done()
        self.create_keyfile.setText(key_file_path)

    def show_create_startmenu_entry(self):
        """ Shown after successfull unlock with setup dialog -> ask for shortcut creation """
        message = (_('<b>Successfully unlocked!</b>\n\n'
                     'Do you want to create\n'
                     'a startup menu entry for <b>{device_name}</b>?\n\n'
                     '-> Your password will NOT be saved!\n'
                     '   This just creates a shortcut,\n'
                     '   to the unlock container dialog.\n').format(
                         device_name=self.get_luks_device_name()))
        mb = QMessageBox(QMessageBox.Question, '', message,
                         QMessageBox.Ok | QMessageBox.Cancel, self)
        mb.button(QMessageBox.Ok).setText(_('Create shortcut'))
        mb.button(QMessageBox.Cancel).setText(_('No, thanks'))
        if mb.exec_() == QMessageBox.Ok:
            self.create_startmenu_entry()

    def create_startmenu_entry(self):
        """ Creates a startmenu entry that lets the user skip the setup dialog and go directly to the main UI
            Includes a workaround for the safety net some desktop environments create around the startupmenu
        """
        import random
        import string
        # command to be saved in shortcut: calling the script with the arguments entered in the dialog
        # put all arguments in single quotes and escape those in the strings (shell escape ' -> '\'')
        cmd = os.path.abspath(sys.argv[0])
        cmd += " -c '" + self.get_encrypted_container().replace("'",
                                                                "'\\'''") + "'"
        cmd += " -n '" + self.get_luks_device_name().replace("'",
                                                             "'\\'''") + "'"
        if self.get_mount_point() is not None:
            cmd += " -m '" + self.get_mount_point().replace("'",
                                                            "'\\'''") + "'"
        if self.get_keyfile() is not None:
            cmd += " -k '" + self.get_keyfile().replace("'", "'\\'''") + "'"

        # create .desktop-file
        filename = _('luckyLUKS') + '-' + ''.join(
            i for i in self.get_luks_device_name() if i not in ' \/:*?<>|'
        )  # xdg-desktop-menu has problems with some special chars
        if is_installed('xdg-desktop-menu'
                        ):  # create in tmp and add freedesktop menu entry
            # some desktop menus dont delete the .desktop files if a user removes items from the menu but keep track of those files instead
            # those items wont be readded later, the random part of the filename works around this behaviour
            desktop_file_path = os.path.join(
                '/tmp', filename + '-' +
                ''.join(random.choice(string.ascii_letters)
                        for i in range(4)) + '.desktop')
        else:  # or create in users home dir
            desktop_file_path = os.path.join(os.path.expanduser('~'),
                                             filename + '.desktop')

        desktop_file = codecs.open(desktop_file_path, 'w', 'utf-8')

        entry_name = _('Unlock {device_name}').format(
            device_name=self.get_luks_device_name())
        desktop_file.write("[Desktop Entry]\n")
        desktop_file.write("Name=" + entry_name + "\n")
        desktop_file.write("Comment=" + self.get_luks_device_name() + " " +
                           _('Encrypted Container Tool') + "\n")
        desktop_file.write("GenericName=" + _('Encrypted Container') + "\n")
        desktop_file.write("Categories=Utility;\n")
        desktop_file.write("Exec=" + cmd + "\n")
        desktop_file.write("Icon=dialog-password\n")
        desktop_file.write("NoDisplay=false\n")
        desktop_file.write("StartupNotify=false\n")
        desktop_file.write("Terminal=0\n")
        desktop_file.write("TerminalOptions=\n")
        desktop_file.write("Type=Application\n\n")
        desktop_file.close()

        os.chmod(desktop_file_path,
                 0o700)  # some distros need the xbit to trust the desktop file

        if is_installed('xdg-desktop-menu'):
            # safest way to ensure updates: explicit uninstall followed by installing a new desktop file with different random part
            import glob
            for desktopfile in glob.glob(
                    os.path.expanduser('~') + '/.local/share/applications/' +
                    filename + '-*.desktop'):
                with open(os.devnull) as DEVNULL:
                    subprocess.call(
                        ['xdg-desktop-menu', 'uninstall', desktopfile],
                        stdout=DEVNULL,
                        stderr=subprocess.STDOUT)
            try:
                subprocess.check_output([
                    'xdg-desktop-menu', 'install', '--novendor',
                    desktop_file_path
                ],
                                        stderr=subprocess.STDOUT,
                                        universal_newlines=True)
                os.remove(desktop_file_path)  # remove from tmp
                show_info(
                    self,
                    _('<b>` {name} `</b>\nadded to start menu').format(
                        name=entry_name), _('Success'))
            except subprocess.CalledProcessError as cpe:
                home_dir_path = os.path.join(
                    os.path.expanduser('~'),
                    os.path.basename(desktop_file_path))
                # move to homedir instead
                from shutil import move
                move(desktop_file_path, home_dir_path)
                show_alert(self, cpe.output)
                show_info(
                    self,
                    _('Adding to start menu not possible,\nplease place your shortcut manually.\n\nDesktop file saved to\n{location}'
                      ).format(location=home_dir_path))
        else:
            show_info(
                self,
                _('Adding to start menu not possible,\nplease place your shortcut manually.\n\nDesktop file saved to\n{location}'
                  ).format(location=desktop_file_path))

    def reject(self):
        """ Event handler cancel: Ask for confirmation while creating container """
        if self.confirm_close():
            super(SetupDialog, self).reject()

    def closeEvent(self, event):
        """ Event handler close: ask for confirmation while creating container """
        if not self.confirm_close():
            event.ignore()

    def confirm_close(self):
        """ Displays a confirmation dialog if currently busy creating container or keyfile
            :returns: The users decision or True if no create process running
            :rtype: bool
        """
        if self.is_busy:
            message = _(
                'Currently processing your request!\nDo you really want to quit?'
            )
            mb = QMessageBox(QMessageBox.Question, '', message,
                             QMessageBox.Ok | QMessageBox.Cancel, self)
            mb.button(QMessageBox.Ok).setText(_('Quit'))
            return mb.exec_() == QMessageBox.Ok
        else:
            return True

    def on_switchpage_event(self, index):
        """ Event handler for tab switch: change text on OK button (Unlock/Create) """
        new_ok_label = _('Unlock')
        if index == 1:  # create
            if self.create_filesystem_type.currentText() == '':
                show_alert(
                    self,
                    _('No tools to format the filesystem found\n'
                      'Please install, eg for Debian/Ubuntu\n'
                      '`apt-get install e2fslibs ntfs-3g`'))
            new_ok_label = _('Create')
        self.buttons.button(QDialogButtonBox.Ok).setText(new_ok_label)

    def on_select_container_clicked(self):
        """ Triggered by clicking the select button next to container file (unlock) """
        file_path = QFileDialog.getOpenFileName(
            self, _('Please choose a container file'), os.getenv("HOME"))
        if isinstance(file_path,
                      tuple):  # qt5 returns tuple path/selected filter
            file_path = file_path[0]
        self.unlock_container_file.setText(file_path)
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))

    def on_select_mountpoint_clicked(self):
        """ Triggered by clicking the select button next to mount point """
        self.unlock_mountpoint.setText(
            QFileDialog.getExistingDirectory(
                self, _('Please choose a folder as mountpoint'),
                os.getenv("HOME")))
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))

    def on_select_keyfile_clicked(self, tab):
        """ Triggered by clicking the select button next to key file (both unlock and create tab) """
        file_path = QFileDialog.getOpenFileName(self,
                                                _('Please choose a key file'),
                                                os.getenv("HOME"))
        if isinstance(file_path,
                      tuple):  # qt5 returns tuple path/selected filter
            file_path = file_path[0]
        if tab == 'Unlock':
            self.unlock_keyfile.setText(file_path)
        elif tab == 'Create':
            self.create_keyfile.setText(file_path)
        self.buttons.button(QDialogButtonBox.Ok).setText(_(tab))

    def on_save_container_clicked(self):
        """ Triggered by clicking the select button next to container file (create)
            Uses a file dialog to set the path of the container file to be created
        """
        self.create_container_file.setText(
            self.on_save_file(_('new_container.bin')))

    def on_save_file(self, default_filename):
        """ Opens a native file dialog and returns the chosen path of the file to be saved
            The dialog does not allow overwriting existing files - to get this behaviour
            while using native dialogs the QFileDialog has to be reopened on overwrite.
            A bit weird but enables visual consistency with the other file choose dialogs
            :param default_filename: The default filename to be used in the Qt file dialog
            :type default_filename: str/unicode
            :returns: The designated key file path
            :rtype: str/unicode
        """
        def_path = os.path.join(os.getenv("HOME"), default_filename)

        while True:
            save_path = QFileDialog.getSaveFileName(
                self,
                _('Please create a new file'),
                def_path,
                options=QFileDialog.DontConfirmOverwrite)

            save_path = self.encode_qt_output(save_path[0]) if isinstance(
                save_path, tuple) else self.encode_qt_output(save_path)
            self.buttons.button(QDialogButtonBox.Ok).setText(
                _('Create'))  # qt keeps changing this..

            if os.path.exists(save_path):
                show_alert(
                    self,
                    _('File already exists:\n{filename}\n\n'
                      '<b>Please create a new file!</b>').format(
                          filename=save_path))
                def_path = os.path.join(os.path.basename(save_path),
                                        default_filename)
            else:
                return save_path

    def display_progress_percent(self, location, size):
        """ Update value on the container creation progress bar
            :param location: The path of the container file currently being created
            :type location: str
            :param size: The final size the new container in bytes
            :type size: int
        """
        try:
            new_value = int(os.path.getsize(location) / size * 100)
        except Exception:
            new_value = 0
        self.create_progressbars[0].setValue(new_value)

    def get_encrypted_container(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The container file path
            :rtype: str/unicode
        """
        return self.encode_qt_output(self.unlock_container_file.text())

    def get_luks_device_name(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The device name
            :rtype: str/unicode
        """
        return self.encode_qt_output(self.unlock_device_name.text())

    def get_keyfile(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The mount point path
            :rtype: str/unicode or None
        """
        kf = self.encode_qt_output(self.unlock_keyfile.text())
        return kf if kf != '' else None

    def get_mount_point(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The mount point path
            :rtype: str/unicode or None
        """
        mp = self.encode_qt_output(self.unlock_mountpoint.text())
        return mp if mp != '' else None

    def encode_qt_output(self, qstring_or_str):
        """ Normalize output from QLineEdit
            :param qstring_or_str: Output from QLineEdit.text()
            :type qstring_or_str: str/QString
            :returns: python unicode (instead of QString in py2)
            :rtype: str/unicode
        """
        try:
            return qstring_or_str.strip()
        except AttributeError:  # py2: 'QString' object has no attribute strip
            return unicode(qstring_or_str.trimmed().toUtf8(), encoding="UTF-8")

    def show_help_create(self):
        """ Triggered by clicking the help button (create tab) """
        header_text = _('<b>Create a new encrypted container</b>\n')
        basic_help = _(
            'Enter the path of the <b>new container file</b> in the textbox '
            'or click the button next to the box for a graphical create file dialog.'
            '\n\n'
            'The <b>device name</b> will be used to identify the unlocked container. '
            'It can be any name up to 16 unicode characters, as long as it is unique.'
            '\n\n'
            'The <b>size</b> of the container can be provided in GB or MB. The container '
            'will get initialized with random data, this can take quite a while - '
            '1 hour for a 10GB container on an external drive is nothing unusual.'
        )
        advanced_topics = [{
            'head':
            _('key file'),
            'text':
            _('A key file can be used to allow access to an encrypted container instead of a password. '
              'Using a key file resembles unlocking a door with a key in the real world - anyone with '
              'access to the key file can open your encrypted container. Make sure to store it at a '
              'protected location. Its okay to store it on your computer if you are using an already '
              'encrypted harddrive or a digital keystore. Having the key file on a '
              '<a href="https://www.google.com/search?q=keychain+usb+drive">small USB drive</a> '
              'attached to your real chain of keys would be an option as well.\n'
              'Since you dont have to enter a password, using a key file can be a convenient way to '
              'access your encrypted container. Just make sure you dont lose the key (file) ;)'
              ) +
            _('\n\n'
              'Although basically any file could be used as a key file, a file with predictable content '
              'leads to similar problems as using weak passwords. Audio files or pictures are a good choice. '
              'If unsure use the `create key file` button to generate a small key file filled with random data.'
              )
        }, {
            'head':
            _('encryption format'),
            'text':
            _('The standard disk encryption format on Linux is called LUKS. '
              'With <a href="https://github.com/t-d-k/doxbox">doxbox</a> you can use LUKS containers on Windows as well. '
              'The TrueCrypt format is quite popular on Windows/Mac, and can be created '
              'on Linux if `tcplay` is installed. Please note, that "hidden" TrueCrypt '
              'partitions are not supported by luckyLUKS!')
        }, {
            'head':
            _('filesystem'),
            'text':
            _('Choose the ntfs filesystem to be able to access your data from Linux, '
              'Windows and Mac OSX. Since access permissions cannot be mapped from '
              'ntfs to Linux, access to ntfs devices is usually not restricted '
              '-> take care when using unlocked ntfs devices in a multiuser environment!'
              )
        }]
        hd = HelpDialog(self, header_text, basic_help, advanced_topics)
        hd.exec_()

    def show_help_unlock(self):
        """ Triggered by clicking the help button (unlock tab) """
        header_text = _('<b>Unlock an encrypted container</b>\n')
        basic_help = _(
            'Select the encrypted <b>container file</b> by clicking the button next to '
            'the textbox. Both LUKS and Truecrypt containers are supported!'
            '\n\n'
            'The <b>device name</b> will be used to identify the unlocked container. '
            'It can be any name up to 16 unicode characters, as long as it is unique '
            '-> you cannot give two unlocked containers the same name')
        advanced_topics = [{
            'head':
            _('key file'),
            'text':
            _('A key file can be used to allow access to an encrypted container instead of a password. '
              'Using a key file resembles unlocking a door with a key in the real world - anyone with '
              'access to the key file can open your encrypted container. Make sure to store it at a '
              'protected location. Its okay to store it on your computer if you are using an already '
              'encrypted harddrive or a digital keystore. Having the key file on a '
              '<a href="https://www.google.com/search?q=keychain+usb+drive">small USB drive</a> '
              'attached to your real chain of keys would be an option as well.\n'
              'Since you dont have to enter a password, using a key file can be a convenient way to '
              'access your encrypted container. Just make sure you dont lose the key (file) ;)'
              )
        }, {
            'head':
            _('mount point'),
            'text':
            _('The mount point is the folder on your computer, where you can '
              'access the files inside the container after unlocking. '
              'If automatic mounting is configured on your system (eg with udisks), '
              'explicitly setting a mountpoint is not neccessary (but still possible).'
              )
        }]
        hd = HelpDialog(self, header_text, basic_help, advanced_topics)
        hd.exec_()
예제 #11
0
class materials_main(QWidgetSavePos):
    def changed_click(self):
        if self.notebook.tabText(self.notebook.currentIndex()).strip() == _(
                "Electrical parameters"):
            help_window().help_set_help([
                "tab.png",
                _("<big><b>Electrical parameters</b></big><br>Use this tab to configure the electrical parameters for the material."
                  )
            ])
            self.ribbon.tb_save.setEnabled(False)
            self.ribbon.import_data.setEnabled(False)

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Luminescence"):
            help_window().help_set_help([
                "tab.png",
                _("<big><b>Luminescence</b></big><br>Use this tab to edit the materials Luminescence."
                  )
            ])
            self.ribbon.tb_save.setEnabled(False)
            self.ribbon.import_data.setEnabled(False)

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Absorption"):
            text = get_ref_text(os.path.join(self.path, "alpha.ref"))
            if text == None:
                text = ""
            help_window().help_set_help(
                ["alpha.png",
                 _("<big><b>Absorption</b></big><br>" + text)])
            self.ribbon.tb_save.setEnabled(True)
            self.ribbon.import_data.setEnabled(True)

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Refractive index"):
            text = get_ref_text(os.path.join(self.path, "n.ref"))
            if text == None:
                text = ""
            help_window().help_set_help(
                ["n.png",
                 _("<big><b>Refractive index</b></big><br>" + text)])
            self.ribbon.tb_save.setEnabled(True)
            self.ribbon.import_data.setEnabled(True)

    def callback_cost(self):
        desktop_open(os.path.join(self.path, "cost.xlsx"))

    def callback_help(self):
        webbrowser.open("https://www.gpvdm.com/man/index.html")

    def __init__(self, path):
        QWidgetSavePos.__init__(self, "materials_main")
        self.path = path
        self.setFixedSize(900, 600)
        self.setWindowIcon(icon_get("organic_material"))

        self.setWindowTitle(
            _("Material editor") + " (https://www.gpvdm.com)" + " " +
            os.path.basename(self.path))

        self.main_vbox = QVBoxLayout()

        self.ribbon = ribbon_materials()

        self.ribbon.cost.triggered.connect(self.callback_cost)
        self.ribbon.folder_open.triggered.connect(self.callback_dir_open)
        self.ribbon.import_data.triggered.connect(self.import_data)
        self.ribbon.tb_ref.triggered.connect(self.callback_ref)

        self.ribbon.help.triggered.connect(self.callback_help)

        self.main_vbox.addWidget(self.ribbon)

        self.notebook = QTabWidget()

        self.notebook.setMovable(True)

        self.main_vbox.addWidget(self.notebook)

        #alpha=equation(self.path,"alpha_eq.inp","alpha_gen.omat","alpha.omat","#mat_default_file_alpha")
        #alpha.set_default_value("1e7")
        #alpha.set_ylabel(_("Absorption")+" (m^{-1})")
        #alpha.init()

        fname = os.path.join(self.path, "alpha.omat")
        self.alpha = plot_widget()
        self.alpha.init(enable_toolbar=False)
        self.alpha.set_labels([_("Absorption")])
        self.alpha.load_data([fname], os.path.splitext(fname)[0] + ".oplot")

        self.alpha.do_plot()
        self.notebook.addTab(self.alpha, _("Absorption"))

        fname = os.path.join(self.path, "n.omat")
        self.n = plot_widget()
        self.n.init(enable_toolbar=False)
        self.n.set_labels([_("Refractive index")])
        self.n.load_data([fname], os.path.splitext(fname)[0] + ".oplot")
        self.n.do_plot()

        self.notebook.addTab(self.n, _("Refractive index"))

        files = ["dos.inp", "pl.inp", "mat.inp"]
        description = [
            _("Electrical parameters"),
            _("Luminescence"),
            _("Basic")
        ]

        for i in range(0, len(files)):
            tab = tab_class()
            full_path = os.path.join(self.path, files[i])
            if os.path.isfile(full_path) == True:
                tab.init(os.path.join(self.path, files[i]), description[i])
                self.notebook.addTab(tab, description[i])
        self.setLayout(self.main_vbox)

        self.notebook.currentChanged.connect(self.changed_click)

    def import_data(self):
        file_name = None
        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Absorption"):
            file_name = "alpha.omat"

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Refractive index"):
            file_name = "n.omat"

        if file_name != None:
            output_file = os.path.join(self.path, file_name)
            config_file = os.path.join(self.path, file_name + "import.inp")
            self.im = import_data(output_file, config_file)
            self.im.run()
            self.update()

    def import_ref(self):
        file_name = None
        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Absorption"):
            file_name = "alpha.omat"

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Refractive index"):
            file_name = "n.omat"

        if file_name != None:
            output_file = os.path.join(self.path, file_name)
            config_file = os.path.join(self.path, file_name + "import.inp")
            self.im = import_data(output_file, config_file)
            self.im.run()
            self.update()

    def update(self):
        self.n.update()
        self.alpha.update()

    def callback_ref(self):
        file_name = None
        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Absorption"):
            file_name = "alpha.omat"

        if self.notebook.tabText(
                self.notebook.currentIndex()).strip() == _("Refractive index"):
            file_name = "n.omat"

        if file_name != None:
            self.ref_window = ref_window(os.path.join(self.path, file_name))
            self.ref_window.show()

    def callback_dir_open(self):
        dialog = gpvdm_open(self.path)
        dialog.show_inp_files = False
        ret = dialog.exec_()

        if ret == QDialog.Accepted:
            desktop_open(dialog.get_filename())
예제 #12
0
class MainWindow(QMainWindow):
    def __init__(self, iris, settings, parent=None, **kwargs):
        QMainWindow.__init__(self, parent)
        self._splash = QSplashScreen(self, QPixmap('data/logo.tif'))
        self._splash.show()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle(
            "Iris Control GUI - %s - Caution use at your own risk!" %
            kwargs['handle']['label'])
        self.setMinimumSize(800, 600)
        self._settings = settings

        #start the window
        self._controlTabs = QTabWidget(self)
        self.setCentralWidget(self._controlTabs)
        self._mainTab = HighLevelControlTab(iris, [0, 1], self._controlTabs)
        self._controlTabs.addTab(self._mainTab, "Main")
        for name, chans, start, stop in [
            ('LML', [
                0,
            ], 0x0000, 0x002F),
            ('TxTSP', [0, 1], 0x0200, 0x020C),
            ('RxTSP', [0, 1], 0x0400, 0x040D),
            ('SXX', [0, 1], 0x011C, 0x0124),
            ('RFE', [0, 1], 0x010C, 0x0114),
            ('RBB', [0, 1], 0x0115, 0x011B),
            ('TRF', [0, 1], 0x0100, 0x0104),
            ('TBB', [0, 1], 0x0105, 0x010B),
            ('EN_DIR', [
                0,
            ], 0x0081, 0x0081),
            ('LDO', [
                0,
            ], 0x0092, 0x00A7),
            ('DC', [
                0,
            ], 0x05C0, 0x05CC),
            ('AFE', [
                0,
            ], 0x0082, 0x0082),
            ('BIAS', [
                0,
            ], 0x0083, 0x0084),
            ('XBUF', [
                0,
            ], 0x0085, 0x0085),
            ('CGEN', [
                0,
            ], 0x0086, 0x008D),
            ('RSSI', [
                0,
            ], 0x0600, 0x0641),
        ]:
            scroll = QScrollArea(self._controlTabs)
            tab = LowLevelControlTab(iris, chans, start, stop, scroll)
            scroll.setWidget(tab)
            self._controlTabs.addTab(scroll, name)

        #load previous settings
        print("Loading %s" % self._settings.fileName())
        if self._settings.contains("MainWindow/geometry"):
            self.restoreGeometry(self._settings.value("MainWindow/geometry"))
        if self._settings.contains("MainWindow/state"):
            self.restoreState(self._settings.value("MainWindow/state"))
        if self._settings.contains("MainWindow/tab"):
            self._controlTabs.setCurrentIndex(
                int(self._settings.value("MainWindow/tab")))

        #load complete
        self._splash.finish(self)

    def loadFile(self, filePath):
        self._mainTab.loadFile(filePath)

    def closeEvent(self, event):

        #stash settings
        self._settings.setValue("MainWindow/geometry", self.saveGeometry())
        self._settings.setValue("MainWindow/state", self.saveState())
        self._settings.setValue("MainWindow/tab",
                                self._controlTabs.currentIndex())
class FramelessWindow(QWidget):
    # 四周边距
    Margins = 2
    # 窗口移动
    windowMoved = pyqtSignal(QPoint)

    def __init__(self):
        super(FramelessWindow, self).__init__()
        self.tab_ = {}
        self.initTab()
        # 初始化一个 tab
        self.newTab()

        self._pressed = False
        self.Direction = None
        # 背景透明
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        # 无边框
        self.setWindowFlags(Qt.FramelessWindowHint)  # 隐藏边框
        # 鼠标跟踪
        self.setMouseTracking(True)
        # 布局
        layout = QVBoxLayout(self, spacing=0)
        # 预留边界用于实现无边框窗口调整大小
        layout.setContentsMargins(self.Margins, self.Margins, self.Margins, self.Margins)
        # 标题栏
        self.titleBar = TitleBar(self)
        # layout = QGridLayout(self, spacing=0)
        # layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.titleBar)
        # self.titleBar.layout.addChildWidget(self.tabWidget.tabBar())
        # self.layout().addWidget(self.titleBar)
        self.titleBar.layout.addChildWidget(self.tabWidget.tabBar())
        self.titleBar.loadFnBtn()
        # self.addPage = QAction(QIcon(':/icons/plus.png'), '页面缩小', self)
        # QTabBar.setS
        self.layout().addWidget(self.tabWidget)
        self.titleBar.addPaged.connect(self.newTab)

        self.statusBar = QStatusBar()
        layout.addWidget(self.statusBar)
        self.headStatusBarLabel = QLabel("就绪")
        self.headStatusBarLabel.setObjectName("headStatusBarLabel")
        self.statusBar.addWidget(self.headStatusBarLabel)

        # 网页加载标签
        self.statusBarLabel = QLabel("网页加载")
        self.statusBarLabel.setObjectName("statusBarLabel")
        self.statusBar.addPermanentWidget(self.statusBarLabel)

        # 网页加载进度条
        self.statusBarLabelProgress = QProgressBar(self)
        self.statusBar.addPermanentWidget(self.statusBarLabelProgress)
        self.statusBarLabelProgress.setObjectName("statusBarLabelProgress")
        self.statusBarLabelProgress.setFixedWidth(200)
        self.statusBarLabelProgress.setHidden(True)
        self.statusBarLabel.setHidden(True)
        # 文件下载标签
        self.statusBarDownloadLabel = QLabel("")
        self.statusBarDownloadLabel.setObjectName("statusBarDownloadLabel")
        self.statusBar.addPermanentWidget(self.statusBarDownloadLabel)
        self.statusBarDownloadLabel.setHidden(True)

        self.statusBar.setHidden(True)
        self.statusBar.setCursor(Qt.ArrowCursor)

        # 信号槽
        self.titleBar.windowMinimumed.connect(self.showMinimized)
        self.titleBar.windowMaximumed.connect(self.showMaximized)
        self.titleBar.windowNormaled.connect(self.showNormal)
        self.titleBar.windowClosed.connect(self.close)
        self.tabBar.windowMoved.connect(self.move)
        # self.titleBar.windowMoved.connect(self.move)
        # self.windowTitleChanged.connect(self.titleBar.setTitle)
        # self.windowIconChanged.connect(self.titleBar.setIcon)
        self.show()

    def initTab(self):
        # print("initTab")
        # self.setWindowFlags(Qt.FramelessWindowHint)  # 去掉标题栏的代码
        # 设置窗口标题
        self.setWindowTitle('PyQt浏览器 v2.0')
        # 设置窗口图标
        self.setWindowIcon(QIcon(':/icons/logo.png'))
        self.tabWidget = QTabWidget()
        # self.tabWidget.setTabBarAutoHide(True)
        self.tabBar = TabBarDe(self)
        # self.tabBar.addAction()
        self.tabWidget.setTabBar(self.tabBar)
        # self.tabWidget.setTabShape(QTabWidget.Triangular) # QTabWidget.Triangular
        self.tabWidget.setDocumentMode(True)
        self.tabWidget.setMovable(True)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.close_Tab)
        self.tabWidget.currentChanged.connect(self.changeTab)

        # self.tabWidget.tabBar().setAutoHide(True)
        height = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) // 2
        width = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) // 2
        self.setMinimumSize(QSize(height * 0.7, width * 0.7))
        # self.center()
        # self.show()

    def newTab(self):
        # print("new tab")
        test = QPushButton("test")
        self.tab = QWidget()
        self.tabWidget.addTab(self.tab, "新标签页")
        self.tabWidget.setCurrentWidget(self.tab)
        index = self.tabWidget.currentIndex()
        try:
            self.tabWidget.setTabIcon(index, QIcon(":icons/earth_128.png"))
        except BaseException as base:
            print(base)
        #####
        self.Layout = QVBoxLayout(self.tab)
        self.Layout.setContentsMargins(0, 0, 0, 0)
        self.browser = Browser(self)
        self.browser.webview.setObjectName(str(index))
        self.tab.setObjectName("tab_" + str(index))
        self.tab_[str(index)] = self.browser.webview
        self.Layout.addWidget(self.browser)

    # 关闭tab
    def close_Tab(self, index):
        if self.tabWidget.count() > 1:
            # self.browser.webview.page().url(QUrl(""))
            # print(self.tab_[str(index)])

            webObj_index = str(self.tabWidget.widget(index).objectName()).split("_")[1]
            # self.tab_[webObj_index].page().setUrl(QUrl(NEW_PAGE))
            # self.tab_[webObj_index].deleteLater()
            print(self.tab_[webObj_index].history())
            self.tab_.pop(webObj_index)
            # print(self.tab_)
            self.tabWidget.removeTab(index)
            # print(index)
            # self.browser.on_windowCloseRequested()
        else:
            self.close()  # 当只有1个tab时,关闭主窗口

    def changeTab(self, index):
        # print("index:%d" % (index))
        pass

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def setTitleBarHeight(self, height=34):
        """设置标题栏高度"""
        self.titleBar.setHeight(height)

    def setIconSize(self, size):
        """设置图标的大小"""
        self.titleBar.setIconSize(size)

    def setWidget(self, widget):
        """设置自己的控件"""
        if hasattr(self, '_widget'):
            return
        self._widget = widget
        # 设置默认背景颜色,否则由于受到父窗口的影响导致透明
        self._widget.setAutoFillBackground(True)
        palette = self._widget.palette()
        palette.setColor(palette.Window, QColor(240, 240, 240))
        self._widget.setPalette(palette)
        self._widget.installEventFilter(self)
        self.layout().addWidget(self._widget)

    def move(self, pos):
        if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen:
            # 最大化或者全屏则不允许移动
            return
        super(FramelessWindow, self).move(pos)

    def showMaximized(self):
        """最大化,要去除上下左右边界,如果不去除则边框地方会有空隙"""
        super(FramelessWindow, self).showMaximized()
        self.layout().setContentsMargins(0, 0, 0, 0)

    def showFullScreen(self):
        super(FramelessWindow, self).showFullScreen()
        self.layout().setContentsMargins(0, 0, 0, 0)

    def showNormal(self):
        """还原,要保留上下左右边界,否则没有边框无法调整"""
        super(FramelessWindow, self).showNormal()
        self.layout().setContentsMargins(
            self.Margins, self.Margins, self.Margins, self.Margins)

    def eventFilter(self, obj, event):
        """事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式"""
        if isinstance(event, QEnterEvent):
            self.setCursor(Qt.ArrowCursor)
        return super(FramelessWindow, self).eventFilter(obj, event)

    def paintEvent(self, event):
        """由于是全透明背景窗口,重绘事件中绘制透明度为1的难以发现的边框,用于调整窗口大小"""
        super(FramelessWindow, self).paintEvent(event)
        painter = QPainter(self)
        painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.Margins))
        painter.drawRect(self.rect())

    def mousePressEvent(self, event):
        """鼠标点击事件"""
        super(FramelessWindow, self).mousePressEvent(event)
        if event.button() == Qt.LeftButton:
            self._mpos = event.pos()
            self._pressed = True

    def mouseReleaseEvent(self, event):
        '''鼠标弹起事件'''
        super(FramelessWindow, self).mouseReleaseEvent(event)
        self._pressed = False
        self.Direction = None

    def mouseMoveEvent(self, event):
        """鼠标移动事件"""
        super(FramelessWindow, self).mouseMoveEvent(event)
        pos = event.pos()
        xPos, yPos = pos.x(), pos.y()
        wm, hm = self.width() - self.Margins, self.height() - self.Margins
        if self.isMaximized() or self.isFullScreen():
            self.Direction = None
            self.setCursor(Qt.ArrowCursor)
            return
        if event.buttons() == Qt.LeftButton and self._pressed:
            self._resizeWidget(pos)
            return
        if xPos <= self.Margins and yPos <= self.Margins:
            # 左上角
            self.Direction = LeftTop
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= xPos <= self.width() and hm <= yPos <= self.height():
            # 右下角
            self.Direction = RightBottom
            self.setCursor(Qt.SizeFDiagCursor)
        elif wm <= xPos and yPos <= self.Margins:
            # 右上角
            self.Direction = RightTop
            self.setCursor(Qt.SizeBDiagCursor)
        elif xPos <= self.Margins and hm <= yPos:
            # 左下角
            self.Direction = LeftBottom
            self.setCursor(Qt.SizeBDiagCursor)
        elif 0 <= xPos <= self.Margins and self.Margins <= yPos <= hm:
            # 左边
            self.Direction = Left
            self.setCursor(Qt.SizeHorCursor)
        elif wm <= xPos <= self.width() and self.Margins <= yPos <= hm:
            # 右边
            self.Direction = Right
            self.setCursor(Qt.SizeHorCursor)
        elif self.Margins <= xPos <= wm and 0 <= yPos <= self.Margins:
            # 上面
            self.Direction = Top
            self.setCursor(Qt.SizeVerCursor)
        elif self.Margins <= xPos <= wm and hm <= yPos <= self.height():
            # 下面
            self.Direction = Bottom
            self.setCursor(Qt.SizeVerCursor)

    def _resizeWidget(self, pos):
        """调整窗口大小"""
        if self.Direction == None:
            return
        mpos = pos - self._mpos
        xPos, yPos = mpos.x(), mpos.y()
        geometry = self.geometry()
        x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height()
        if self.Direction == LeftTop:  # 左上角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
        elif self.Direction == RightBottom:  # 右下角
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos = pos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos = pos
        elif self.Direction == RightTop:  # 右上角
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos.setX(pos.x())
        elif self.Direction == LeftBottom:  # 左下角
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos.setY(pos.y())
        elif self.Direction == Left:  # 左边
            if w - xPos > self.minimumWidth():
                x += xPos
                w -= xPos
            else:
                return
        elif self.Direction == Right:  # 右边
            if w + xPos > self.minimumWidth():
                w += xPos
                self._mpos = pos
            else:
                return
        elif self.Direction == Top:  # 上面
            if h - yPos > self.minimumHeight():
                y += yPos
                h -= yPos
            else:
                return
        elif self.Direction == Bottom:  # 下面
            if h + yPos > self.minimumHeight():
                h += yPos
                self._mpos = pos
            else:
                return
        self.setGeometry(x, y, w, h)
예제 #14
0
class ReTextWindow(QMainWindow):
	def __init__(self, parent=None):
		QMainWindow.__init__(self, parent)
		self.resize(950, 700)
		screenRect = QDesktopWidget().screenGeometry()
		if globalSettings.windowGeometry:
			self.restoreGeometry(globalSettings.windowGeometry)
		else:
			self.move((screenRect.width()-self.width())/2, (screenRect.height()-self.height())/2)
		if not screenRect.contains(self.geometry()):
			self.showMaximized()
		if sys.platform.startswith('darwin'):
			# https://github.com/retext-project/retext/issues/198
			searchPaths = QIcon.themeSearchPaths()
			searchPaths.append('/opt/local/share/icons')
			searchPaths.append('/usr/local/share/icons')
			QIcon.setThemeSearchPaths(searchPaths)
		if globalSettings.iconTheme:
			QIcon.setThemeName(globalSettings.iconTheme)
		if QIcon.themeName() in ('hicolor', ''):
			if not QFile.exists(icon_path + 'document-new.png'):
				QIcon.setThemeName(get_icon_theme())
		if QFile.exists(icon_path+'retext.png'):
			self.setWindowIcon(QIcon(icon_path+'retext.png'))
		elif QFile.exists('/usr/share/pixmaps/retext.png'):
			self.setWindowIcon(QIcon('/usr/share/pixmaps/retext.png'))
		else:
			self.setWindowIcon(QIcon.fromTheme('retext',
				QIcon.fromTheme('accessories-text-editor')))
		self.tabWidget = QTabWidget(self)
		self.initTabWidget()
		self.setCentralWidget(self.tabWidget)
		self.tabWidget.currentChanged.connect(self.changeIndex)
		self.tabWidget.tabCloseRequested.connect(self.closeTab)
		toolBar = QToolBar(self.tr('File toolbar'), self)
		self.addToolBar(Qt.TopToolBarArea, toolBar)
		self.editBar = QToolBar(self.tr('Edit toolbar'), self)
		self.addToolBar(Qt.TopToolBarArea, self.editBar)
		self.searchBar = QToolBar(self.tr('Search toolbar'), self)
		self.addToolBar(Qt.BottomToolBarArea, self.searchBar)
		toolBar.setVisible(not globalSettings.hideToolBar)
		self.editBar.setVisible(not globalSettings.hideToolBar)
		self.actionNew = self.act(self.tr('New'), 'document-new',
			self.createNew, shct=QKeySequence.New)
		self.actionNew.setPriority(QAction.LowPriority)
		self.actionOpen = self.act(self.tr('Open'), 'document-open',
			self.openFile, shct=QKeySequence.Open)
		self.actionOpen.setPriority(QAction.LowPriority)
		self.actionSetEncoding = self.act(self.tr('Set encoding'),
			trig=self.showEncodingDialog)
		self.actionSetEncoding.setEnabled(False)
		self.actionReload = self.act(self.tr('Reload'), 'view-refresh',
			lambda: self.currentTab.readTextFromFile())
		self.actionReload.setEnabled(False)
		self.actionSave = self.act(self.tr('Save'), 'document-save',
			self.saveFile, shct=QKeySequence.Save)
		self.actionSave.setEnabled(False)
		self.actionSave.setPriority(QAction.LowPriority)
		self.actionSaveAs = self.act(self.tr('Save as'), 'document-save-as',
			self.saveFileAs, shct=QKeySequence.SaveAs)
		self.actionNextTab = self.act(self.tr('Next tab'), 'go-next',
			lambda: self.switchTab(1), shct=Qt.CTRL+Qt.Key_PageDown)
		self.actionPrevTab = self.act(self.tr('Previous tab'), 'go-previous',
			lambda: self.switchTab(-1), shct=Qt.CTRL+Qt.Key_PageUp)
		self.actionPrint = self.act(self.tr('Print'), 'document-print',
			self.printFile, shct=QKeySequence.Print)
		self.actionPrint.setPriority(QAction.LowPriority)
		self.actionPrintPreview = self.act(self.tr('Print preview'), 'document-print-preview',
			self.printPreview)
		self.actionViewHtml = self.act(self.tr('View HTML code'), 'text-html', self.viewHtml)
		self.actionChangeEditorFont = self.act(self.tr('Change editor font'),
			trig=self.changeEditorFont)
		self.actionChangePreviewFont = self.act(self.tr('Change preview font'),
			trig=self.changePreviewFont)
		self.actionSearch = self.act(self.tr('Find text'), 'edit-find', shct=QKeySequence.Find)
		self.actionSearch.setCheckable(True)
		self.actionSearch.triggered[bool].connect(self.searchBar.setVisible)
		self.searchBar.visibilityChanged.connect(self.searchBarVisibilityChanged)
		self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E,
			trigbool=self.preview)
		if QIcon.hasThemeIcon('document-preview'):
			self.actionPreview.setIcon(QIcon.fromTheme('document-preview'))
		elif QIcon.hasThemeIcon('preview-file'):
			self.actionPreview.setIcon(QIcon.fromTheme('preview-file'))
		elif QIcon.hasThemeIcon('x-office-document'):
			self.actionPreview.setIcon(QIcon.fromTheme('x-office-document'))
		else:
			self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png'))
		self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L,
		trigbool=self.enableLivePreview)
		menuPreview = QMenu()
		menuPreview.addAction(self.actionLivePreview)
		self.actionPreview.setMenu(menuPreview)
		self.actionTableMode = self.act(self.tr('Table editing mode'),
			shct=Qt.CTRL+Qt.Key_T,
			trigbool=lambda x: self.currentTab.editBox.enableTableMode(x))
		if ReTextFakeVimHandler:
			self.actionFakeVimMode = self.act(self.tr('FakeVim mode'),
				shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode)
			if globalSettings.useFakeVim:
				self.actionFakeVimMode.setChecked(True)
				self.enableFakeVimMode(True)
		self.actionFullScreen = self.act(self.tr('Fullscreen mode'), 'view-fullscreen',
			shct=Qt.Key_F11, trigbool=self.enableFullScreen)
		self.actionFullScreen.setPriority(QAction.LowPriority)
		self.actionConfig = self.act(self.tr('Preferences'), icon='preferences-system',
			trig=self.openConfigDialog)
		self.actionConfig.setMenuRole(QAction.PreferencesRole)
		self.actionSaveHtml = self.act('HTML', 'text-html', self.saveFileHtml)
		self.actionPdf = self.act('PDF', 'application-pdf', self.savePdf)
		self.actionOdf = self.act('ODT', 'x-office-document', self.saveOdf)
		self.getExportExtensionsList()
		self.actionQuit = self.act(self.tr('Quit'), 'application-exit', shct=QKeySequence.Quit)
		self.actionQuit.setMenuRole(QAction.QuitRole)
		self.actionQuit.triggered.connect(self.close)
		self.actionUndo = self.act(self.tr('Undo'), 'edit-undo',
			lambda: self.currentTab.editBox.undo(), shct=QKeySequence.Undo)
		self.actionRedo = self.act(self.tr('Redo'), 'edit-redo',
			lambda: self.currentTab.editBox.redo(), shct=QKeySequence.Redo)
		self.actionCopy = self.act(self.tr('Copy'), 'edit-copy',
			lambda: self.currentTab.editBox.copy(), shct=QKeySequence.Copy)
		self.actionCut = self.act(self.tr('Cut'), 'edit-cut',
			lambda: self.currentTab.editBox.cut(), shct=QKeySequence.Cut)
		self.actionPaste = self.act(self.tr('Paste'), 'edit-paste',
			lambda: self.currentTab.editBox.paste(), shct=QKeySequence.Paste)
		self.actionUndo.setEnabled(False)
		self.actionRedo.setEnabled(False)
		self.actionCopy.setEnabled(False)
		self.actionCut.setEnabled(False)
		qApp = QApplication.instance()
		qApp.clipboard().dataChanged.connect(self.clipboardDataChanged)
		self.clipboardDataChanged()
		if enchant is not None:
			self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck)
			self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale)
		self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit)
		if ReTextWebPreview is None:
			globalSettings.useWebKit = False
			self.actionWebKit.setEnabled(False)
		self.actionWebKit.setChecked(globalSettings.useWebKit)
		self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir)
		self.actionFind = self.act(self.tr('Next'), 'go-next', self.find,
			shct=QKeySequence.FindNext)
		self.actionFindPrev = self.act(self.tr('Previous'), 'go-previous',
			lambda: self.find(back=True), shct=QKeySequence.FindPrevious)
		self.actionReplace = self.act(self.tr('Replace'), 'edit-find-replace',
			lambda: self.find(replace=True))
		self.actionReplaceAll = self.act(self.tr('Replace all'), trig=self.replaceAll)
		menuReplace = QMenu()
		menuReplace.addAction(self.actionReplaceAll)
		self.actionReplace.setMenu(menuReplace)
		self.actionCloseSearch = self.act(self.tr('Close'), 'window-close',
			lambda: self.searchBar.setVisible(False))
		self.actionCloseSearch.setPriority(QAction.LowPriority)
		self.actionHelp = self.act(self.tr('Get help online'), 'help-contents', self.openHelp)
		self.aboutWindowTitle = self.tr('About ReText')
		self.actionAbout = self.act(self.aboutWindowTitle, 'help-about', self.aboutDialog)
		self.actionAbout.setMenuRole(QAction.AboutRole)
		self.actionAboutQt = self.act(self.tr('About Qt'))
		self.actionAboutQt.setMenuRole(QAction.AboutQtRole)
		self.actionAboutQt.triggered.connect(qApp.aboutQt)
		availableMarkups = markups.get_available_markups()
		if not availableMarkups:
			print('Warning: no markups are available!')
		if len(availableMarkups) > 1:
			self.chooseGroup = QActionGroup(self)
			markupActions = []
			for markup in availableMarkups:
				markupAction = self.act(markup.name, trigbool=self.markupFunction(markup))
				if markup.name == globalSettings.defaultMarkup:
					markupAction.setChecked(True)
				self.chooseGroup.addAction(markupAction)
				markupActions.append(markupAction)
		self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold,
			trig=lambda: self.insertFormatting('bold'))
		self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic,
			trig=lambda: self.insertFormatting('italic'))
		self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline,
			trig=lambda: self.insertFormatting('underline'))
		self.usefulTags = ('header', 'italic', 'bold', 'underline', 'numbering',
			'bullets', 'image', 'link', 'inline code', 'code block', 'blockquote')
		self.usefulChars = ('deg', 'divide', 'dollar', 'hellip', 'laquo', 'larr',
			'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo',
			'rarr', 'rsquo', 'times')
		self.formattingBox = QComboBox(self.editBar)
		self.formattingBox.addItem(self.tr('Formatting'))
		self.formattingBox.addItems(self.usefulTags)
		self.formattingBox.activated[str].connect(self.insertFormatting)
		self.symbolBox = QComboBox(self.editBar)
		self.symbolBox.addItem(self.tr('Symbols'))
		self.symbolBox.addItems(self.usefulChars)
		self.symbolBox.activated.connect(self.insertSymbol)
		self.updateStyleSheet()
		menubar = self.menuBar()
		menuFile = menubar.addMenu(self.tr('File'))
		menuEdit = menubar.addMenu(self.tr('Edit'))
		menuHelp = menubar.addMenu(self.tr('Help'))
		menuFile.addAction(self.actionNew)
		menuFile.addAction(self.actionOpen)
		self.menuRecentFiles = menuFile.addMenu(self.tr('Open recent'))
		self.menuRecentFiles.aboutToShow.connect(self.updateRecentFiles)
		menuFile.addAction(self.actionShow)
		menuFile.addAction(self.actionSetEncoding)
		menuFile.addAction(self.actionReload)
		menuFile.addSeparator()
		menuFile.addAction(self.actionSave)
		menuFile.addAction(self.actionSaveAs)
		menuFile.addSeparator()
		menuFile.addAction(self.actionNextTab)
		menuFile.addAction(self.actionPrevTab)
		menuFile.addSeparator()
		menuExport = menuFile.addMenu(self.tr('Export'))
		menuExport.addAction(self.actionSaveHtml)
		menuExport.addAction(self.actionOdf)
		menuExport.addAction(self.actionPdf)
		if self.extensionActions:
			menuExport.addSeparator()
			for action, mimetype in self.extensionActions:
				menuExport.addAction(action)
			menuExport.aboutToShow.connect(self.updateExtensionsVisibility)
		menuFile.addAction(self.actionPrint)
		menuFile.addAction(self.actionPrintPreview)
		menuFile.addSeparator()
		menuFile.addAction(self.actionQuit)
		menuEdit.addAction(self.actionUndo)
		menuEdit.addAction(self.actionRedo)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionCut)
		menuEdit.addAction(self.actionCopy)
		menuEdit.addAction(self.actionPaste)
		menuEdit.addSeparator()
		if enchant is not None:
			menuSC = menuEdit.addMenu(self.tr('Spell check'))
			menuSC.addAction(self.actionEnableSC)
			menuSC.addAction(self.actionSetLocale)
		menuEdit.addAction(self.actionSearch)
		menuEdit.addAction(self.actionChangeEditorFont)
		menuEdit.addAction(self.actionChangePreviewFont)
		menuEdit.addSeparator()
		if len(availableMarkups) > 1:
			self.menuMode = menuEdit.addMenu(self.tr('Default markup'))
			for markupAction in markupActions:
				self.menuMode.addAction(markupAction)
		menuFormat = menuEdit.addMenu(self.tr('Formatting'))
		menuFormat.addAction(self.actionBold)
		menuFormat.addAction(self.actionItalic)
		menuFormat.addAction(self.actionUnderline)
		menuEdit.addAction(self.actionWebKit)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionViewHtml)
		menuEdit.addAction(self.actionPreview)
		menuEdit.addAction(self.actionTableMode)
		if ReTextFakeVimHandler:
			menuEdit.addAction(self.actionFakeVimMode)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionFullScreen)
		menuEdit.addAction(self.actionConfig)
		menuHelp.addAction(self.actionHelp)
		menuHelp.addSeparator()
		menuHelp.addAction(self.actionAbout)
		menuHelp.addAction(self.actionAboutQt)
		toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		toolBar.addAction(self.actionNew)
		toolBar.addSeparator()
		toolBar.addAction(self.actionOpen)
		toolBar.addAction(self.actionSave)
		toolBar.addAction(self.actionPrint)
		toolBar.addSeparator()
		toolBar.addAction(self.actionPreview)
		toolBar.addAction(self.actionFullScreen)
		self.editBar.addAction(self.actionUndo)
		self.editBar.addAction(self.actionRedo)
		self.editBar.addSeparator()
		self.editBar.addAction(self.actionCut)
		self.editBar.addAction(self.actionCopy)
		self.editBar.addAction(self.actionPaste)
		self.editBar.addSeparator()
		self.editBar.addWidget(self.formattingBox)
		self.editBar.addWidget(self.symbolBox)
		self.searchEdit = QLineEdit(self.searchBar)
		self.searchEdit.setPlaceholderText(self.tr('Search'))
		self.searchEdit.returnPressed.connect(self.find)
		self.replaceEdit = QLineEdit(self.searchBar)
		self.replaceEdit.setPlaceholderText(self.tr('Replace with'))
		self.replaceEdit.returnPressed.connect(self.find)
		self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar)
		self.searchBar.addWidget(self.searchEdit)
		self.searchBar.addWidget(self.replaceEdit)
		self.searchBar.addSeparator()
		self.searchBar.addWidget(self.csBox)
		self.searchBar.addAction(self.actionFindPrev)
		self.searchBar.addAction(self.actionFind)
		self.searchBar.addAction(self.actionReplace)
		self.searchBar.addAction(self.actionCloseSearch)
		self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		self.searchBar.setVisible(False)
		self.autoSaveEnabled = globalSettings.autoSave
		if self.autoSaveEnabled:
			timer = QTimer(self)
			timer.start(60000)
			timer.timeout.connect(self.saveAll)
		self.ind = None
		if enchant is not None:
			self.sl = globalSettings.spellCheckLocale
			try:
				enchant.Dict(self.sl or None)
			except enchant.errors.Error as e:
				print(e, file=sys.stderr)
				globalSettings.spellCheck = False
			if globalSettings.spellCheck:
				self.actionEnableSC.setChecked(True)
		self.fileSystemWatcher = QFileSystemWatcher()
		self.fileSystemWatcher.fileChanged.connect(self.fileChanged)

	def restoreLastOpenedFiles(self):
		for file in readListFromSettings("lastFileList"):
			self.openFileWrapper(file)

		# Show the tab of last opened file
		lastTabIndex = globalSettings.lastTabIndex
		if lastTabIndex >= 0 and lastTabIndex < self.tabWidget.count():
			self.tabWidget.setCurrentIndex(lastTabIndex)

	def iterateTabs(self):
		for i in range(self.tabWidget.count()):
			yield self.tabWidget.widget(i)

	def updateStyleSheet(self):
		if globalSettings.styleSheet:
			sheetfile = QFile(globalSettings.styleSheet)
			sheetfile.open(QIODevice.ReadOnly)
			self.ss = QTextStream(sheetfile).readAll()
			sheetfile.close()
		else:
			palette = QApplication.palette()
			self.ss = 'html { color: %s; }\n' % palette.color(QPalette.WindowText).name()
			self.ss += 'td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }\n'
			self.ss += 'table { border-collapse: collapse; }\n'

	def initTabWidget(self):
		def dragEnterEvent(e):
			e.acceptProposedAction()
		def dropEvent(e):
			fn = bytes(e.mimeData().data('text/plain')).decode().rstrip()
			if fn.startswith('file:'):
				fn = QUrl(fn).toLocalFile()
			self.openFileWrapper(fn)
		self.tabWidget.setTabsClosable(True)
		self.tabWidget.setAcceptDrops(True)
		self.tabWidget.setMovable(True)
		self.tabWidget.dragEnterEvent = dragEnterEvent
		self.tabWidget.dropEvent = dropEvent
		if hasattr(self.tabWidget, 'setTabBarAutoHide'):
			self.tabWidget.setTabBarAutoHide(globalSettings.tabBarAutoHide)

	def act(self, name, icon=None, trig=None, trigbool=None, shct=None):
		if not isinstance(shct, QKeySequence):
			shct = QKeySequence(shct)
		if icon:
			action = QAction(self.actIcon(icon), name, self)
		else:
			action = QAction(name, self)
		if trig:
			action.triggered.connect(trig)
		elif trigbool:
			action.setCheckable(True)
			action.triggered[bool].connect(trigbool)
		if shct:
			action.setShortcut(shct)
		return action

	def actIcon(self, name):
		return QIcon.fromTheme(name, QIcon(icon_path+name+'.png'))

	def printError(self):
		import traceback
		print('Exception occurred while parsing document:', file=sys.stderr)
		traceback.print_exc()


	def tabFileNameChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		filename of the current tab has changed.
		'''
		if tab == self.currentTab:
			if tab.fileName:
				self.setWindowTitle("")
				self.setWindowFilePath(tab.fileName)
				self.tabWidget.setTabText(self.ind, tab.getBaseName())
				self.tabWidget.setTabToolTip(self.ind, tab.fileName)
				QDir.setCurrent(QFileInfo(tab.fileName).dir().path())
			else:
				self.setWindowFilePath('')
				self.setWindowTitle(self.tr('New document') + '[*]')

			canReload = bool(tab.fileName) and not self.autoSaveActive(tab)
			self.actionSetEncoding.setEnabled(canReload)
			self.actionReload.setEnabled(canReload)

	def tabActiveMarkupChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		active markup class of the current tab has changed.
		'''
		if tab == self.currentTab:
			markupClass = tab.getActiveMarkupClass()
			dtMarkdown = (markupClass == markups.MarkdownMarkup)
			dtMkdOrReST = dtMarkdown or (markupClass == markups.ReStructuredTextMarkup)
			self.formattingBox.setEnabled(dtMarkdown)
			self.symbolBox.setEnabled(dtMarkdown)
			self.actionUnderline.setEnabled(dtMarkdown)
			self.actionBold.setEnabled(dtMkdOrReST)
			self.actionItalic.setEnabled(dtMkdOrReST)

	def tabModificationStateChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		modification state of the current tab has changed.
		'''
		if tab == self.currentTab:
			changed = tab.editBox.document().isModified()
			if self.autoSaveActive(tab):
				changed = False
			self.actionSave.setEnabled(changed)
			self.setWindowModified(changed)

	def createTab(self, fileName):
		self.currentTab = ReTextTab(self, fileName,
			previewState=int(globalSettings.livePreviewByDefault))
		self.currentTab.fileNameChanged.connect(lambda: self.tabFileNameChanged(self.currentTab))
		self.currentTab.modificationStateChanged.connect(lambda: self.tabModificationStateChanged(self.currentTab))
		self.currentTab.activeMarkupChanged.connect(lambda: self.tabActiveMarkupChanged(self.currentTab))
		self.tabWidget.addTab(self.currentTab, self.tr("New document"))
		self.currentTab.updateBoxesVisibility()

	def closeTab(self, ind):
		if self.maybeSave(ind):
			if self.tabWidget.count() == 1:
				self.createTab("")
			closedTab = self.tabWidget.widget(ind)
			if closedTab.fileName:
				self.fileSystemWatcher.removePath(closedTab.fileName)
			self.tabWidget.removeTab(ind)
			closedTab.deleteLater()

	def changeIndex(self, ind):
		'''
		This function is called when a different tab is selected.
		It changes the state of the window to mirror the current state
		of the newly selected tab. Future changes to this state will be
		done in response to signals emitted by the tab, to which the
		window was subscribed when the tab was created. The window is
		subscribed to all tabs like this, but only the active tab will
		logically generate these signals.
		Aside from the above this function also calls the handlers for
		the other changes that are implied by a tab switch: filename
		change, modification state change and active markup change.
		'''
		self.currentTab = self.tabWidget.currentWidget()
		editBox = self.currentTab.editBox
		previewState = self.currentTab.previewState
		self.actionUndo.setEnabled(editBox.document().isUndoAvailable())
		self.actionRedo.setEnabled(editBox.document().isRedoAvailable())
		self.actionCopy.setEnabled(editBox.textCursor().hasSelection())
		self.actionCut.setEnabled(editBox.textCursor().hasSelection())
		self.actionPreview.setChecked(previewState >= PreviewLive)
		self.actionLivePreview.setChecked(previewState == PreviewLive)
		self.actionTableMode.setChecked(editBox.tableModeEnabled)
		self.editBar.setEnabled(previewState < PreviewNormal)
		self.ind = ind
		editBox.setFocus(Qt.OtherFocusReason)

		self.tabFileNameChanged(self.currentTab)
		self.tabModificationStateChanged(self.currentTab)
		self.tabActiveMarkupChanged(self.currentTab)

	def changeEditorFont(self):
		font, ok = QFontDialog.getFont(globalSettings.editorFont, self)
		if ok:
			globalSettings.editorFont = font
			for tab in self.iterateTabs():
				tab.editBox.updateFont()

	def changePreviewFont(self):
		font, ok = QFontDialog.getFont(globalSettings.font, self)
		if ok:
			globalSettings.font = font
			for tab in self.iterateTabs():
				tab.triggerPreviewUpdate()

	def preview(self, viewmode):
		self.currentTab.previewState = viewmode * 2
		self.actionLivePreview.setChecked(False)
		self.editBar.setDisabled(viewmode)
		self.currentTab.updateBoxesVisibility()

	def enableLivePreview(self, livemode):
		self.currentTab.previewState = int(livemode)
		self.actionPreview.setChecked(livemode)
		self.editBar.setEnabled(True)
		self.currentTab.updateBoxesVisibility()

	def enableWebKit(self, enable):
		globalSettings.useWebKit = enable
		for tab in self.iterateTabs():
			tab.previewBox.disconnectExternalSignals()
			tab.previewBox.setParent(None)
			tab.previewBox.deleteLater()
			tab.previewBox = tab.createPreviewBox(tab.editBox)
			tab.previewBox.setMinimumWidth(125)
			tab.addWidget(tab.previewBox)
			tab.setSizes((50, 50))
			tab.triggerPreviewUpdate()
			tab.updateBoxesVisibility()

	def enableCopy(self, copymode):
		self.actionCopy.setEnabled(copymode)
		self.actionCut.setEnabled(copymode)

	def enableFullScreen(self, yes):
		if yes:
			self.showFullScreen()
		else:
			self.showNormal()

	def openConfigDialog(self):
		dlg = ConfigDialog(self)
		dlg.setWindowTitle(self.tr('Preferences'))
		dlg.show()

	def enableFakeVimMode(self, yes):
		globalSettings.useFakeVim = yes
		if yes:
			FakeVimMode.init(self)
			for tab in self.iterateTabs():
				tab.editBox.installFakeVimHandler()
		else:
			FakeVimMode.exit(self)

	def enableSpellCheck(self, yes):
		try:
			dict = enchant.Dict(self.sl or None)
		except enchant.errors.Error as e:
			QMessageBox.warning(self, '', str(e))
			self.actionEnableSC.setChecked(False)
			yes = False
		self.setAllDictionaries(dict if yes else None)
		globalSettings.spellCheck = yes

	def setAllDictionaries(self, dictionary):
		for tab in self.iterateTabs():
			hl = tab.highlighter
			hl.dictionary = dictionary
			hl.rehighlight()

	def changeLocale(self):
		localedlg = LocaleDialog(self, defaultText=self.sl)
		if localedlg.exec() != QDialog.Accepted:
			return
		sl = localedlg.localeEdit.text()
		try:
			enchant.Dict(sl or None)
		except enchant.errors.Error as e:
			QMessageBox.warning(self, '', str(e))
		else:
			self.sl = sl or None
			self.enableSpellCheck(self.actionEnableSC.isChecked())
			if localedlg.checkBox.isChecked():
				globalSettings.spellCheckLocale = sl

	def searchBarVisibilityChanged(self, visible):
		self.actionSearch.setChecked(visible)
		if visible:
			self.searchEdit.setFocus(Qt.ShortcutFocusReason)

	def find(self, back=False, replace=False):
		flags = QTextDocument.FindFlags()
		if back:
			flags |= QTextDocument.FindBackward
		if self.csBox.isChecked():
			flags |= QTextDocument.FindCaseSensitively
		text = self.searchEdit.text()
		replaceText = self.replaceEdit.text() if replace else None
		found = self.currentTab.find(text, flags, replaceText=replaceText)
		self.setSearchEditColor(found)

	def replaceAll(self):
		text = self.searchEdit.text()
		replaceText = self.replaceEdit.text()
		found = self.currentTab.replaceAll(text, replaceText)
		self.setSearchEditColor(found)

	def setSearchEditColor(self, found):
		palette = self.searchEdit.palette()
		palette.setColor(QPalette.Active, QPalette.Base,
		                 Qt.white if found else QColor(255, 102, 102))
		self.searchEdit.setPalette(palette)

	def showInDir(self):
		if self.currentTab.fileName:
			path = QFileInfo(self.currentTab.fileName).path()
			QDesktopServices.openUrl(QUrl.fromLocalFile(path))
		else:
			QMessageBox.warning(self, '', self.tr("Please, save the file somewhere."))

	def moveToTopOfRecentFileList(self, fileName):
		if fileName:
			files = readListFromSettings("recentFileList")
			if fileName in files:
				files.remove(fileName)
			files.insert(0, fileName)
			if len(files) > 10:
				del files[10:]
			writeListToSettings("recentFileList", files)

	def createNew(self, text=None):
		self.createTab("")
		self.ind = self.tabWidget.count()-1
		self.tabWidget.setCurrentIndex(self.ind)
		if text:
			self.currentTab.editBox.textCursor().insertText(text)

	def switchTab(self, shift=1):
		self.tabWidget.setCurrentIndex((self.ind + shift) % self.tabWidget.count())

	def updateRecentFiles(self):
		self.menuRecentFiles.clear()
		self.recentFilesActions = []
		filesOld = readListFromSettings("recentFileList")
		files = []
		for f in filesOld:
			if QFile.exists(f):
				files.append(f)
				self.recentFilesActions.append(self.act(f, trig=self.openFunction(f)))
		writeListToSettings("recentFileList", files)
		for action in self.recentFilesActions:
			self.menuRecentFiles.addAction(action)

	def markupFunction(self, markup):
		return lambda: self.setDefaultMarkup(markup)

	def openFunction(self, fileName):
		return lambda: self.openFileWrapper(fileName)

	def extensionFunction(self, data):
		return lambda: \
		self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension'])

	def getExportExtensionsList(self):
		extensions = []
		for extsprefix in datadirs:
			extsdir = QDir(extsprefix+'/export-extensions/')
			if extsdir.exists():
				for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'],
				QDir.Files | QDir.Readable):
					extensions.append(self.readExtension(fileInfo.filePath()))
		locale = QLocale.system().name()
		self.extensionActions = []
		for extension in extensions:
			try:
				if ('Name[%s]' % locale) in extension:
					name = extension['Name[%s]' % locale]
				elif ('Name[%s]' % locale.split('_')[0]) in extension:
					name = extension['Name[%s]' % locale.split('_')[0]]
				else:
					name = extension['Name']
				data = {}
				for prop in ('FileFilter', 'DefaultExtension', 'Exec'):
					if 'X-ReText-'+prop in extension:
						data[prop] = extension['X-ReText-'+prop]
					elif prop in extension:
						data[prop] = extension[prop]
					else:
						data[prop] = ''
				action = self.act(name, trig=self.extensionFunction(data))
				if 'Icon' in extension:
					action.setIcon(self.actIcon(extension['Icon']))
				mimetype = extension['MimeType'] if 'MimeType' in extension else None
			except KeyError:
				print('Failed to parse extension: Name is required', file=sys.stderr)
			else:
				self.extensionActions.append((action, mimetype))

	def updateExtensionsVisibility(self):
		markupClass = self.currentTab.getActiveMarkupClass()
		for action in self.extensionActions:
			if markupClass is None:
				action[0].setEnabled(False)
				continue
			mimetype = action[1]
			if mimetype is None:
				enabled = True
			elif markupClass == markups.MarkdownMarkup:
				enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown", "text/markdown"))
			elif markupClass == markups.ReStructuredTextMarkup:
				enabled = (mimetype in ("text/x-retext-rst", "text/x-rst"))
			else:
				enabled = False
			action[0].setEnabled(enabled)

	def readExtension(self, fileName):
		extFile = QFile(fileName)
		extFile.open(QIODevice.ReadOnly)
		extension = {}
		stream = QTextStream(extFile)
		while not stream.atEnd():
			line = stream.readLine()
			if '=' in line:
				index = line.index('=')
				extension[line[:index].rstrip()] = line[index+1:].lstrip()
		extFile.close()
		return extension

	def openFile(self):
		supportedExtensions = ['.txt']
		for markup in markups.get_all_markups():
			supportedExtensions += markup.file_extensions
		fileFilter = ' (' + str.join(' ', ['*'+ext for ext in supportedExtensions]) + ');;'
		fileNames = QFileDialog.getOpenFileNames(self,
			self.tr("Select one or several files to open"), "",
			self.tr("Supported files") + fileFilter + self.tr("All files (*)"))
		for fileName in fileNames[0]:
			self.openFileWrapper(fileName)

	def openFileWrapper(self, fileName):
		if not fileName:
			return
		fileName = QFileInfo(fileName).canonicalFilePath()
		exists = False
		for i, tab in enumerate(self.iterateTabs()):
			if tab.fileName == fileName:
				exists = True
				ex = i
		if exists:
			self.tabWidget.setCurrentIndex(ex)
		elif QFile.exists(fileName):
			noEmptyTab = (
				(self.ind is None) or
				self.currentTab.fileName or
				self.currentTab.editBox.toPlainText() or
				self.currentTab.editBox.document().isModified()
			)
			if noEmptyTab:
				self.createTab(fileName)
				self.ind = self.tabWidget.count()-1
				self.tabWidget.setCurrentIndex(self.ind)
			if fileName:
				self.fileSystemWatcher.addPath(fileName)
			self.currentTab.readTextFromFile(fileName)
			self.moveToTopOfRecentFileList(self.currentTab.fileName)

	def showEncodingDialog(self):
		if not self.maybeSave(self.ind):
			return
		codecsSet = set(bytes(QTextCodec.codecForName(alias).name())
		                for alias in QTextCodec.availableCodecs())
		encoding, ok = QInputDialog.getItem(self, '',
			self.tr('Select file encoding from the list:'),
			[bytes(b).decode() for b in sorted(codecsSet)],
			0, False)
		if ok:
			self.currentTab.readTextFromFile(None, encoding)

	def saveFileAs(self):
		self.saveFile(dlg=True)

	def saveAll(self):
		for tab in self.iterateTabs():
			if tab.fileName and QFileInfo(tab.fileName).isWritable():
				tab.saveTextToFile()

	def saveFile(self, dlg=False):
		fileNameToSave = self.currentTab.fileName

		if (not fileNameToSave) or dlg:
			markupClass = self.currentTab.getActiveMarkupClass()
			if (markupClass is None) or not hasattr(markupClass, 'default_extension'):
				defaultExt = self.tr("Plain text (*.txt)")
				ext = ".txt"
			else:
				defaultExt = self.tr('%s files',
					'Example of final string: Markdown files') \
					% markupClass.name + ' (' + str.join(' ',
					('*'+extension for extension in markupClass.file_extensions)) + ')'
				if markupClass == markups.MarkdownMarkup:
					ext = globalSettings.markdownDefaultFileExtension
				elif markupClass == markups.ReStructuredTextMarkup:
					ext = globalSettings.restDefaultFileExtension
				else:
					ext = markupClass.default_extension
			fileNameToSave = QFileDialog.getSaveFileName(self,
				self.tr("Save file"), "", defaultExt)[0]
			if fileNameToSave:
				if not QFileInfo(fileNameToSave).suffix():
					fileNameToSave += ext
				# Make sure we don't overwrite a file opened in other tab
				for tab in self.iterateTabs():
					if tab is not self.currentTab and tab.fileName == fileNameToSave:
						QMessageBox.warning(self, "",
							self.tr("Cannot save to file which is open in another tab!"))
						return False
				self.actionSetEncoding.setDisabled(self.autoSaveActive())
		if fileNameToSave:
			if self.currentTab.saveTextToFile(fileNameToSave):
				self.moveToTopOfRecentFileList(self.currentTab.fileName)
				return True
			else:
				QMessageBox.warning(self, '',
				self.tr("Cannot save to file because it is read-only!"))
		return False

	def saveHtml(self, fileName):
		if not QFileInfo(fileName).suffix():
			fileName += ".html"
		try:
			_, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False,
				                                              webenv=True)
		except Exception:
			return self.printError()
		htmlFile = QFile(fileName)
		htmlFile.open(QIODevice.WriteOnly)
		html = QTextStream(htmlFile)
		if globalSettings.defaultCodec:
			html.setCodec(globalSettings.defaultCodec)
		html << htmltext
		htmlFile.close()

	def textDocument(self, title, htmltext):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, title)
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(htmltext)
		td.setDefaultFont(globalSettings.font)
		return td

	def saveOdf(self):
		title, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=True,
		                                                          webenv=False)
		try:
			document = self.textDocument(title, htmltext)
		except Exception:
			return self.printError()
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Export document to ODT"), "",
			self.tr("OpenDocument text files (*.odt)"))[0]
		if not QFileInfo(fileName).suffix():
			fileName += ".odt"
		writer = QTextDocumentWriter(fileName)
		writer.setFormat(b"odf")
		writer.write(document)

	def saveFileHtml(self):
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Save file"), "",
			self.tr("HTML files (*.html *.htm)"))[0]
		if fileName:
			self.saveHtml(fileName)

	def getDocumentForPrint(self, title, htmltext, preview):
		if globalSettings.useWebKit:
			return preview
		try:
			return self.textDocument(title, htmltext)
		except Exception:
			self.printError()

	def standardPrinter(self, title):
		printer = QPrinter(QPrinter.HighResolution)
		printer.setDocName(title)
		printer.setCreator('ReText %s' % app_version)
		return printer

	def savePdf(self):
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Export document to PDF"),
			"", self.tr("PDF files (*.pdf)"))[0]
		if fileName:
			if not QFileInfo(fileName).suffix():
				fileName += ".pdf"
			title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										        webenv=False)
			printer = self.standardPrinter(title)
			printer.setOutputFormat(QPrinter.PdfFormat)
			printer.setOutputFileName(fileName)
			document = self.getDocumentForPrint(title, htmltext, preview)
			if document != None:
				document.print(printer)

	def printFile(self):
		title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										webenv=False)
		printer = self.standardPrinter(title)
		dlg = QPrintDialog(printer, self)
		dlg.setWindowTitle(self.tr("Print document"))
		if (dlg.exec() == QDialog.Accepted):
			document = self.getDocumentForPrint(title, htmltext, preview)
			if document != None:
				document.print(printer)

	def printPreview(self):
		title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										webenv=False)
		document = self.getDocumentForPrint(title, htmltext, preview)
		if document is None:
			return
		printer = self.standardPrinter(title)
		preview = QPrintPreviewDialog(printer, self)
		preview.paintRequested.connect(document.print)
		preview.exec()

	def runExtensionCommand(self, command, filefilter, defaultext):
		import shlex
		of = ('%of' in command)
		html = ('%html' in command)
		if of:
			if defaultext and not filefilter:
				filefilter = '*'+defaultext
			fileName = QFileDialog.getSaveFileName(self,
				self.tr('Export document'), '', filefilter)[0]
			if not fileName:
				return
			if defaultext and not QFileInfo(fileName).suffix():
				fileName += defaultext
		else:
			fileName = 'out' + defaultext
		basename = '.%s.retext-temp' % self.currentTab.getBaseName()
		if html:
			tmpname = basename+'.html'
			self.saveHtml(tmpname)
		else:
			tmpname = basename + self.currentTab.getActiveMarkupClass().default_extension
			self.currentTab.writeTextToFile(tmpname)
		command = command.replace('%of', shlex.quote(fileName))
		command = command.replace('%html' if html else '%if', shlex.quote(tmpname))
		try:
			Popen(str(command), shell=True).wait()
		except Exception as error:
			errorstr = str(error)
			QMessageBox.warning(self, '', self.tr('Failed to execute the command:')
			+ '\n' + errorstr)
		QFile(tmpname).remove()

	def autoSaveActive(self, tab=None):
		tab = tab if tab else self.currentTab
		return bool(self.autoSaveEnabled and tab.fileName and
			    QFileInfo(tab.fileName).isWritable())

	def clipboardDataChanged(self):
		mimeData = QApplication.instance().clipboard().mimeData()
		if mimeData is not None:
			self.actionPaste.setEnabled(mimeData.hasText() or mimeData.hasImage())

	def insertFormatting(self, formatting):
		cursor = self.currentTab.editBox.textCursor()
		text = cursor.selectedText()
		moveCursorTo = None

		def c(cursor):
			nonlocal moveCursorTo
			moveCursorTo = cursor.position()

		def ensurenl(cursor):
			if not cursor.atBlockStart():
				cursor.insertText('\n\n')

		toinsert = {
			'header': (ensurenl, '# ', text),
			'italic': ('*', text, c, '*'),
			'bold': ('**', text, c, '**'),
			'underline': ('<u>', text, c, '</u>'),
			'numbering': (ensurenl, ' 1. ', text),
			'bullets': (ensurenl, '  * ', text),
			'image': ('![', text or self.tr('Alt text'), c, '](', self.tr('URL'), ')'),
			'link': ('[', text or self.tr('Link text'), c, '](', self.tr('URL'), ')'),
			'inline code': ('`', text, c, '`'),
			'code block': (ensurenl, '    ', text),
			'blockquote': (ensurenl, '> ', text),
		}

		if formatting not in toinsert:
			return

		cursor.beginEditBlock()
		for token in toinsert[formatting]:
			if callable(token):
				token(cursor)
			else:
				cursor.insertText(token)
		cursor.endEditBlock()

		self.formattingBox.setCurrentIndex(0)
		# Bring back the focus on the editor
		self.currentTab.editBox.setFocus(Qt.OtherFocusReason)

		if moveCursorTo:
			cursor.setPosition(moveCursorTo)
			self.currentTab.editBox.setTextCursor(cursor)

	def insertSymbol(self, num):
		if num:
			self.currentTab.editBox.insertPlainText('&'+self.usefulChars[num-1]+';')
		self.symbolBox.setCurrentIndex(0)

	def fileChanged(self, fileName):
		ind = None
		for testind, tab in enumerate(self.iterateTabs()):
			if tab.fileName == fileName:
				ind = testind
		if ind is None:
			self.fileSystemWatcher.removePath(fileName)
		self.tabWidget.setCurrentIndex(ind)
		if not QFile.exists(fileName):
			self.currentTab.editBox.document().setModified(True)
			QMessageBox.warning(self, '', self.tr(
				'This file has been deleted by other application.\n'
				'Please make sure you save the file before exit.'))
		elif not self.currentTab.editBox.document().isModified():
			# File was not modified in ReText, reload silently
			self.currentTab.readTextFromFile()
		else:
			text = self.tr(
				'This document has been modified by other application.\n'
				'Do you want to reload the file (this will discard all '
				'your changes)?\n')
			if self.autoSaveEnabled:
				text += self.tr(
					'If you choose to not reload the file, auto save mode will '
					'be disabled for this session to prevent data loss.')
			messageBox = QMessageBox(QMessageBox.Warning, '', text)
			reloadButton = messageBox.addButton(self.tr('Reload'), QMessageBox.YesRole)
			messageBox.addButton(QMessageBox.Cancel)
			messageBox.exec()
			if messageBox.clickedButton() is reloadButton:
				self.currentTab.readTextFromFile()
			else:
				self.autoSaveEnabled = False
				self.currentTab.editBox.document().setModified(True)
		if fileName not in self.fileSystemWatcher.files():
			# https://github.com/retext-project/retext/issues/137
			self.fileSystemWatcher.addPath(fileName)

	def maybeSave(self, ind):
		tab = self.tabWidget.widget(ind)
		if self.autoSaveActive(tab):
			tab.saveTextToFile()
			return True
		if not tab.editBox.document().isModified():
			return True
		self.tabWidget.setCurrentIndex(ind)
		ret = QMessageBox.warning(self, '',
			self.tr("The document has been modified.\nDo you want to save your changes?"),
			QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
		if ret == QMessageBox.Save:
			return self.saveFile(False)
		elif ret == QMessageBox.Cancel:
			return False
		return True

	def closeEvent(self, closeevent):
		for ind in range(self.tabWidget.count()):
			if not self.maybeSave(ind):
				return closeevent.ignore()
		if globalSettings.saveWindowGeometry and not self.isMaximized():
			globalSettings.windowGeometry = self.saveGeometry()
		if globalSettings.openLastFilesOnStartup:
			files = [tab.fileName for tab in self.iterateTabs()]
			writeListToSettings("lastFileList", files)
			globalSettings.lastTabIndex = self.tabWidget.currentIndex()
		closeevent.accept()

	def viewHtml(self):
		htmlDlg = HtmlDialog(self)
		try:
			_, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False,
			                                                      webenv=False)
		except Exception:
			return self.printError()
		winTitle = self.currentTab.getBaseName()
		htmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+")")
		htmlDlg.textEdit.setPlainText(htmltext.rstrip())
		htmlDlg.hl.rehighlight()
		htmlDlg.show()
		htmlDlg.raise_()
		htmlDlg.activateWindow()

	def openHelp(self):
		QDesktopServices.openUrl(QUrl('https://github.com/retext-project/retext/wiki'))

	def aboutDialog(self):
		QMessageBox.about(self, self.aboutWindowTitle,
		'<p><b>' + (self.tr('ReText %s (using PyMarkups %s)') % (app_version, markups.__version__))
		+'</b></p>' + self.tr('Simple but powerful editor'
		' for Markdown and reStructuredText')
		+'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011').replace('2011', '2011–2016')
		+'<br><a href="https://github.com/retext-project/retext">'+self.tr('Website')
		+'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">'
		+self.tr('Markdown syntax')
		+'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">'
		+self.tr('reStructuredText syntax')+'</a></p>')

	def setDefaultMarkup(self, markupClass):
		globalSettings.defaultMarkup = markupClass.name
		for tab in self.iterateTabs():
			if not tab.fileName:
				tab.updateActiveMarkupClass()
예제 #15
0
파일: configpanel.py 프로젝트: reiser4/amc
class ConfigurationPanel(QMainWindow):
    """docstring for ConfigurationPanel"""
    def __init__(self):
        super(ConfigurationPanel, self).__init__()
        self.bands = ["6m", "10m", "12m", "15m", "17m", "20m", "30m", "40m", "60m", "80m", "160m"]
        self.nrow = 16
        self.nrele = 24
        # creo le azioni che usero' in seguito
        self.initAction()
        self.initUI()

    def initUI(self):
        # imposto la grandezza del font
        self.setStyleSheet('font-size: 11pt;')
        # imposto le dimensioni della finestra
        self.setGeometry(0, 0, 1500, 600)
        # imposto il titolo della finestra
        self.setWindowTitle("AMC Configuration Panel")
        # creo il menu'
        self.initMenuBar()
        self.initToolBar()
        # creo le tab ed il loro contenuto
        self.initTab()
        # imposta il widget dato come widget centrale della finestra principale
        self.setCentralWidget(self.tab_widget)
        # sposta la finestra al centro del desktop
        self.centerOnScreen()
        # visualizzo il widget
        self.show()
        # visualizzo la scritta 'Ready' nella status bar
        self.statusBar().showMessage("Ready")

    def initAction(self):
        # TODO: sistemare il path delle icone
        # azione per uscire dall'applicazione
        self.exitAction = QAction(
            QIcon(os.path.join("icons", "exit.png")),
            "&Exit",
            self)
        self.exitAction.setShortcut("Ctrl+Q")
        self.exitAction.setStatusTip("Exit application")
        # collego l'azione exitAction all'evento self.close (gia' presente in PyQT)
        self.exitAction.triggered.connect(self.close)

        # azione per caricare la configurazione da file
        self.openAction = QAction(
            QIcon(os.path.join("icons", "open-configuration.png")),
            "&Load configuration",
            self)
        self.openAction.setShortcut("Ctrl+L")
        self.openAction.setStatusTip("Load to file")
        # collego l'azione openAction al mio evento che ho creato loadConfigurationFile
        self.openAction.triggered.connect(self.loadConfigurationFile)

        # azione per salvare la configurazione su file
        self.saveAction = QAction(
            QIcon(os.path.join("icons", "save-configuration.png")),
            "&Save configuration",
            self)
        self.saveAction.setShortcut("Ctrl+S")
        self.saveAction.setStatusTip("Save to file")
        self.saveAction.triggered.connect(self.saveConfigurationFile)

        # azione per spedire la configurazione al beaglebone
        self.uploadAction = QAction(
            QIcon(os.path.join("icons", "upload-configuration.png")),
            "&Upload configuration",
            self)
        self.uploadAction.setShortcut("Ctrl+U")
        self.uploadAction.setStatusTip("Upload to beaglebone")
        self.uploadAction.triggered.connect(self.uploadConfiguration)

        # azione per ricevere la configurazione dal beaglebone
        self.downloadAction = QAction(
            QIcon(os.path.join("icons", "download-configuration.png")),
            "&Download configuration",
            self)
        self.downloadAction.setShortcut("Ctrl+D")
        self.downloadAction.setStatusTip("Download from beaglebone")
        self.downloadAction.triggered.connect(self.downloadConfiguration)

        """
        serialAction = QAction("&Serial", self)
        serialAction.setShortcut("")
        serialAction.setStatusTip("")
        serialAction.triggered.connect()

        downloadAction = QAction("&Download", self)
        downloadAction.setShortcut("")
        downloadAction.setStatusTip("")
        downloadAction.triggered.connect()

        UploadAction = QAction("&Upload", self)
        UploadAction.setShortcut("")
        UploadAction.setStatusTip("")
        UploadAction.triggered.connect()
        """

    def initMenuBar(self):
        # creo il menu ed aggiungo i vari campi
        menubar = self.menuBar()
        filemenu = menubar.addMenu("&File")
        filemenu.addAction(self.openAction)
        filemenu.addAction(self.saveAction)
        filemenu.addSeparator()
        filemenu.addAction(self.downloadAction)
        filemenu.addAction(self.uploadAction)
        filemenu.addSeparator()
        # aggancio al menu il comando per uscire
        filemenu.addAction(self.exitAction)

        #configuration_menu = menubar.addMenu("&Configuration")
        #configuration_menu.addAction(self.saveAction)
        #configuration_menu.addSeparator()
        #configuration_menu.addAction(self.openAction)
        #connection_menu = menubar.addMenu("&Connection")

    def initToolBar(self):
        toolbar = self.addToolBar('ToolBar')
        toolbar.addAction(self.saveAction)
        toolbar.addSeparator()
        toolbar.addAction(self.openAction)
        toolbar.addSeparator()
        toolbar.addAction(self.downloadAction)
        toolbar.addSeparator()
        toolbar.addAction(self.uploadAction)

    def initTab(self):
        # creo un TabWidget che sara' il widget padre
        self.tab_widget = QTabWidget(self)
        labels_name = ["Active", "Label", "Bands"]
        tab_list = list()
        self.tablayout_list = list()
        self.checkbox_matrix = list()
        self.labels_matrix = list()
        self.radio1cb_matrix = list()
        self.radio2cb_matrix = list()
        for i in range(len(self.bands)):
            # aggiungo alla lista un oggetto QWidget discendente dal padre
            tab_list.append(QWidget(self.tab_widget))
            # per ogni nome band aggiungo una tab nella list che
            # sara' visualizzata nella finestra principale
            self.tab_widget.addTab(tab_list[i], self.bands[i])
            # aggiungo alla lista un oggetto per il layout a griglia discendente
            # dalla i-esima tab
            self.tablayout_list.append(QGridLayout(tab_list[i]))
            self.tablayout_list[i].setObjectName("tab" + str(i).zfill(2))
            #print (self.tablayout_list[i].objectName())
            # nella i-esima tab creo un layout a griglia e posiziono i vari elementi
            boldfont = QFont()
            boldfont.setBold(True)
            active_lbl = QLabel('Active:', tab_list[i])
            active_lbl.setFont(boldfont)
            label_lbl = QLabel('Label:', tab_list[i])
            label_lbl.setFont(boldfont)
            radio1_lbl = QLabel('Radio 1:', tab_list[i])
            radio1_lbl.setFont(boldfont)
            radio2_lbl = QLabel('Radio 2:', tab_list[i])
            radio2_lbl.setFont(boldfont)
            self.tablayout_list[i].addWidget(active_lbl, 0, 0)
            #self.tablayout_list[i].addWidget(QLabel("Label", tab_list[i]), 0, 1)
            self.tablayout_list[i].addWidget(label_lbl, 0, 1)
            #self.tablayout_list[i].addWidget(QLabel("Radio 1", tab_list[i]), 0, 2, 1, self.nrele)
            self.tablayout_list[i].addWidget(radio1_lbl, 0, 2, 1, self.nrele)
            #self.tablayout_list[i].addWidget(QLabel("Radio 2", tab_list[i]), 0, 26, 1, self.nrele)
            self.tablayout_list[i].addWidget(radio2_lbl, 0, 26, 1, self.nrele)
            self.checkbox_matrix.append(list())
            self.labels_matrix.append(list())
            self.radio1cb_matrix.append(list())
            self.radio2cb_matrix.append(list())
            # per ogni tab devo creare tutti i suoi oggetti al suo interno
            for y in range(self.nrow):
                self.checkbox_matrix[i].append(QCheckBox(tab_list[i]))
                self.checkbox_matrix[i][y].setObjectName("checkboxRowTab" + str(i).zfill(2))
                self.checkbox_matrix[i][y].setCheckState(Qt.Unchecked)
                self.checkbox_matrix[i][y].stateChanged.connect(self.changeStateRow)
                #self.checkbox_matrix[i][y].setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
                self.tablayout_list[i].addWidget(self.checkbox_matrix[i][y], y+1, 0)
                self.labels_matrix[i].append(QLineEdit(tab_list[i]))
                self.labels_matrix[i][y].setEnabled(False)
                self.tablayout_list[i].addWidget(self.labels_matrix[i][y], y+1, 1)
                self.radio1cb_matrix[i].append(list())
                self.radio2cb_matrix[i].append(list())
                for z in range(self.nrele):
                    self.radio1cb_matrix[i][y].append(QCheckBox(tab_list[i]))
                    #self.radio1cb_matrix[i][y][z].setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
                    #self.radio1cb_matrix[i][y][z].stateChanged.connect(self.changeCheckBoxState)
                    self.radio1cb_matrix[i][y][z].setEnabled(False)
                    # aggiungo 1 a y perche' devo contare le etichette (Active, Label, Radio1, Radio2)
                    # aggiungo 2 a z perche' devo tenere conto dei widget di sinistra (checkbox e label)
                    self.tablayout_list[i].addWidget(self.radio1cb_matrix[i][y][z], y+1, z+2)

                    self.radio2cb_matrix[i][y].append(QCheckBox(tab_list[i]))
                    #self.radio2cb_matrix[i][y][z].stateChanged.connect(self.changeCheckBoxState)
                    self.radio2cb_matrix[i][y][z].setEnabled(False)
                    # aggiungo 1 a y perche' devo contare le etichette (Active, Label, Radio1, Radio2)
                    # aggiungo 2 a z perche' devo tenere conto dei widget di sinistra (checkbox, label e 24 checkbox)
                    self.tablayout_list[i].addWidget(self.radio2cb_matrix[i][y][z], y+1, z+26)

    def centerOnScreen(self):
        '''
        Centers the window on the screen.
        '''
        # prende le dimensioni della finestra
        qr = self.frameGeometry()
        # prende il punto centrale del display date le sue dimensioni
        cp = QDesktopWidget().availableGeometry().center()
        # muoviamo la finestra al centro dello schermo
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def warningOpenFile(self):
        QMessageBox.warning(self, 'Errore', "Errore nell'apertura del file")

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Message', "Are you sure to quit?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.close()

    def changeStateRow(self, state):
        if state == Qt.Checked or state == Qt.Unchecked:
            sender = self.sender()
            '''
            Trovare un modo migliore per trovare la posizione dell'oggetto
            che effettua la richiesta perche' questo fa schifo!!!!
            '''
            #print ("Sender: ", sender.objectName())
            # Recupero l'indice della tab dove si trova la checkbox attraverso il nome
            indexTab = int(sender.objectName()[-2:])
            #print ("indexTab: ", indexTab)
            indexPos = self.tablayout_list[indexTab].indexOf(sender)
            #print ("indexPos:", indexPos)
            location = self.tablayout_list[indexTab].getItemPosition(indexPos)
            indexRow = location[0]
            indexColumn = location[1]
            text = "Tab: " + self.bands[indexTab] + ", Row: " + str(indexColumn) + \
                    ", Column: " + str(indexRow) + ", State: " + str(state)
            #print (text)
            self.statusBar().showMessage(text)
            if state == Qt.Checked:
                self.labels_matrix[indexTab][indexRow-1].setEnabled(True)
                for i in range(self.nrele):
                    # -1 perche' e' compresa la riga delle etichette
                    self.radio1cb_matrix[indexTab][indexRow-1][i].setEnabled(True)
                    self.radio2cb_matrix[indexTab][indexRow-1][i].setEnabled(True)
            else:
                self.labels_matrix[indexTab][indexRow-1].setEnabled(False)
                for i in range(self.nrele):
                    self.radio1cb_matrix[indexTab][indexRow-1][i].setEnabled(False)
                    self.radio2cb_matrix[indexTab][indexRow-1][i].setEnabled(False)

    def changeCheckBoxState(self, state):
        '''
        Funzione che stampa a terminale tutte le volte che viene cliccata
        una checkbox
        '''
        if state == Qt.Checked or state == Qt.Unchecked:
        #if True:
            sender = self.sender()
            #self.statusBar().showMessage(sender.text())
            indexTab = self.tab_widget.currentIndex()
            """
            button = self.sender()
            idx = self.layout.indexOf(button)
            location = self.layout.getItemPosition(idx)
            print ("Button", button, "at row/col", location[:2])
            """
            idx = self.tablayout_list[indexTab].indexOf(sender)
            location = self.tablayout_list[indexTab].getItemPosition(idx)
            indexRow = location[0]
            indexColumn = location[1]
            '''
            print ("indexTab: ", indexTab)
            print ("idx:", idx)
            text = "Tab: " + str(indexTab) + ", Row: " + str(indexColumn) + \
                    ", Column: " + str(indexRow) + ", State: " + str(state)
            print (text)
            self.statusBar().showMessage(text)
            '''
            #trovo la banda
            band = self.bands[indexTab]
            presetnumber = indexRow
            if indexColumn > 1 and indexColumn < 26:
                ptype = "radioA, relay " + str(location[1]-1)
            else:
                # -25 perche' sarebbe -26 (numero oggetti) + 1 (perche' non voglio partire da 0 ma da 1)
                ptype = "radioB, relay " + str(location[1]-25) # attenzione alla "label"
            print ("Posizione decodificata: banda ", band, ", preset numero ", presetnumber, ", tipo ", ptype)

    def createJsonConfiguration(self):
        jsonconfig = '{"relayconfig":{\n'
        commaTab = False
        for indexTab in range(len(self.bands)):
            firstRow = True
            nRowChecked = 0
            for indexRow in range(self.nrow):
                if self.checkbox_matrix[indexTab][indexRow].isChecked() == True:
                    nRowChecked += 1
                    if firstRow:
                        if commaTab:
                            # inserisco una virgola per ogni tab a parte l'ultima
                            jsonconfig += ',\n'
                            commaTab = False
                        jsonconfig += '\t"' + self.bands[indexTab] + '":{\n'
                        firstRow = False
                        commaTab = True
                    else:
                        jsonconfig += ',\n'
                    jsonconfig += '\t\t"' + str(indexRow) + '":{\n\t\t\t"label":' + \
                                '"' + self.labels_matrix[indexTab][indexRow].text() + '",\n'
                    relayA = ""
                    relayB = ""
                    for z in range(self.nrele):
                        if self.radio1cb_matrix[indexTab][indexRow][z].isChecked() == True:
                            relayA += "1"
                        else:
                            relayA += "0"
                        if self.radio2cb_matrix[indexTab][indexRow][z].isChecked() == True:
                            relayB += "1"
                        else:
                            relayB += "0"
                    jsonconfig += '\t\t\t"relayA":' + '"' + relayA + '",\n\t\t\t"relayB":' + \
                                '"' + relayB + '"\n\t\t}'
            if nRowChecked > 0:
                # chiudo parentesi prima di label
                jsonconfig += '\n\t}'
        jsonconfig += '\n}}'
        return jsonconfig

    def saveConfigurationFile(self, filename):
        """
        prendo il primo elemento, cioe' 0 perche' getSaveFileName mi restituisce
        una lista del tipo (u'/home/giulio/workspace/amc/test-config.json',
        u'JSON Files (*.json)')
        """
        fname = QFileDialog.getSaveFileName(self, 'Save configuration',
                os.getcwd(), "JSON Files (*.json)")[0]
        if fname:
            #print (fname)
            ###AtomicWrite.writeFile(fname, jsonconfig)
            self.saveConf(fname)
            #print ("Scrittura eseguita correttamente su file")

    def saveConf(self, filename):
        jsonconfig = self.createJsonConfiguration()
        AtomicWrite.writeFile(filename, jsonconfig)

    def loadConfigurationFile(self):
        """
        apre una finestra di selezione in /home dove e' possibile selezionare solo file json
        prendo il primo elemento, cioe' 0 perche' getOpenFileName mi restituisce
        una lista del tipo (u'/home/giulio/workspace/amc/test-config.json',
        u'JSON Files (*.json)')
        """
        fname = QFileDialog.getOpenFileName(self, 'Load configuration',
                os.getcwd(), "JSON Files (*.json)")[0]
        if fname:
            #print (fname)
            try:
                with open(fname, 'r') as fin:
                    config = json.load(fin)
                #print (config)
                for indexTab in range(len(self.bands)):
                    for indexRow in range(self.nrow):
                        if self.checkbox_matrix[indexTab][indexRow].isChecked() == True:
                            self.checkbox_matrix[indexTab][indexRow].setCheckState(Qt.Unchecked)
                for tab in config['relayconfig']:
                    for row in config['relayconfig'][tab]:
                        #print (tab + "-" + row)
                        label = config['relayconfig'][tab][row]['label']
                        relayA = config['relayconfig'][tab][row]['relayA']
                        relayB = config['relayconfig'][tab][row]['relayB']
                        #print (label + relayA + relayB)
                        self.checkbox_matrix[self.bands.index(tab)][int(row)].setCheckState(Qt.Checked)
                        self.labels_matrix[self.bands.index(tab)][int(row)].setText(label)
                        for i in range(self.nrele):
                            if relayA[i] == '1':
                                self.radio1cb_matrix[self.bands.index(tab)][int(row)][i].setCheckState(Qt.Checked)
                            if relayB[i] == '1':
                                self.radio2cb_matrix[self.bands.index(tab)][int(row)][i].setCheckState(Qt.Checked)
            except Exception as e:
                QMessageBox.warning(self, 'Errore', str(e))

    def loadConfiguration(self, config):
        try:
            for indexTab in range(len(self.bands)):
                for indexRow in range(self.nrow):
                    if self.checkbox_matrix[indexTab][indexRow].isChecked() == True:
                        self.checkbox_matrix[indexTab][indexRow].setCheckState(Qt.Unchecked)
            for tab in config['relayconfig']:
                for row in config['relayconfig'][tab]:
                    #print (tab + "-" + row)
                    label = config['relayconfig'][tab][row]['label']
                    relayA = config['relayconfig'][tab][row]['relayA']
                    relayB = config['relayconfig'][tab][row]['relayB']
                    #print (label + relayA + relayB)
                    self.checkbox_matrix[self.bands.index(tab)][int(row)].setCheckState(Qt.Checked)
                    self.labels_matrix[self.bands.index(tab)][int(row)].setText(label)
                    for i in range(self.nrele):
                        if relayA[i] == '1':
                            self.radio1cb_matrix[self.bands.index(tab)][int(row)][i].setCheckState(Qt.Checked)
                        if relayB[i] == '1':
                            self.radio2cb_matrix[self.bands.index(tab)][int(row)][i].setCheckState(Qt.Checked)
        except Exception as e:
            QMessageBox.warning(self, 'Errore', str(e))

    def uploadConfiguration(self):
        self.saveConf("current.json")
        uploadConfiguration_panel = UploadConfigurationPanel()
        #uploadConfiguration_panel.show()
        uploadConfiguration_panel.exec_()

    def downloadConfiguration(self):
        downloadConfiguration_panel = DownloadConfigurationPanel()
        #uploadConfiguration_panel.show()
        downloadConfiguration_panel.exec_()
        config = downloadConfiguration_panel.getConfig()
        if config:
            self.loadConfiguration(config)
class Main(QMainWindow):
    ''' Main class inherits from QMainWindow'''
    def __init__(self):
        ''' initialises the class with essential variables and objects

        :return: None
        '''
        super().__init__()
        self.setWindowTitle('FOSSEE SpreadSheet')
        self.resize(800, 600)
        self.work_books = 1
        self.Tab_widget = QTabWidget()
        self.vBox = QVBoxLayout()
        Central_widget = QWidget()
        Central_widget.setLayout(self.vBox)
        self.work_booksList = []
        self.work_booksList.append(Sheet())
        self.work_booksList[0].setColumnHeaders()
        self.vBox.addWidget(self.Tab_widget)
        self.setTab()
        self.setCentralWidget(Central_widget)
        self.show()
        self.setMenu()

    def setTab(self, index=0, name="Untitled"):
        ''' Add Tabs to QTabWidget for number

        :param index: current index of Tab in QTabWidget
        :param name: sets the title of tab according to csv file name

        :return: None
        '''
        self.Tab_widget.addTab(self.work_booksList[index].form_widget, name)

    def setMenu(self):
        ''' Sets the menu, toolbar, user interface

        :return: None
        '''
        #setup actions
        quit_action = QAction('Quit', self)
        load_action = QAction('Load inputs', self)
        validate_action = QAction('Validate', self)
        submit_action = QAction('Submit', self)
        #setup triggered action
        load_action.triggered.connect(self.open_sheet)
        validate_action.triggered.connect(self.validate_sheet)
        submit_action.triggered.connect(self.submit_sheet)
        quit_action.triggered.connect(self.quit_app)
        #setup Toolbar
        toolbar = QMainWindow.addToolBar(self, 'Toolbar')
        toolbar.addAction(load_action)
        toolbar.addAction(validate_action)
        toolbar.addAction(submit_action)
        toolbar.addAction(quit_action)

    def xlsxToCsv(self, path):
        '''Converts the xlsx file to csv file format for each workbook

        :param path: Directory path for the file

        :return: None
        '''
        wb = xlrd.open_workbook(path, on_demand=True)
        self.work_books = wb.nsheets
        for i in range(self.work_books):
            sh = wb.sheet_by_index(i)
            your_csv_file = open('your_csv_file' + str(i) + '.csv', 'w')
            wr = csv.writer(your_csv_file,
                            quoting=csv.QUOTE_ALL,
                            lineterminator='\n')

            for rownum in range(sh.nrows):
                wr.writerow(sh.row_values(rownum))
            your_csv_file.close()
        return [['your_csv_file' + str(i) + '.csv',
                 wb.sheet_names()[i]] for i in range(self.work_books)]

    def open_sheet(self):
        ''' calls file browser to open the csv,xlsx file

        :return: workbooklist - contains class sheet object list
                  paths - list of path for each csv file
        '''
        paths = ['']
        self.work_booksList[0].form_widget.check_change = False
        path = QFileDialog.getOpenFileName(self, 'Open CSV/XLS',
                                           os.getenv('HOME'),
                                           'CSV(*.csv *.xlsx)')
        if path[0] == '':
            return
        paths[0] = path[0]
        sheet_names = [path[0].split('/')[-1].split('.')[0]]
        if path[0].split('/')[-1].split('.')[-1] == 'xlsx':
            paths.clear()
            paths, sheet_names = list(zip(*self.xlsxToCsv(path[0])))
        else:
            self.work_books = 1
            #changes needed to open multiple WB
        self.work_booksList[0].form_widget.deleteLater()
        self.Tab_widget.removeTab(0)
        self.work_booksList.clear()
        for g in range(self.work_books):
            self.work_booksList.append(Sheet())
            self.setTab(g, sheet_names[g])
            self.work_booksList[g].form_widget.check_change = False

        def Sheets(Workbooks, paths):
            ''' repopulates the each table with each csv file 

            :param Workbooks: list of class sheet objects
            :param paths: list of paths to the each csv files
                        
            :return: None
            '''
            for Workbook, path in zip(Workbooks, paths):
                with open(path, newline='', encoding='utf-8',
                          errors='ignore') as csv_file:
                    Workbook.form_widget.setRowCount(0)
                    #Workbook.form_widget.setColumnCount(10)
                    my_file = csv.reader(csv_file, dialect='excel')
                    fields = next(my_file)
                    Workbook.col_headers = list(
                        filter(lambda x: x != "", fields))
                    if len(fields) < 26:
                        Workbook.form_widget.ncols = len(fields)
                        Workbook.form_widget.setColumnCount(26)
                    Workbook.setColumnHeaders()
                    for row_data in my_file:
                        row = Workbook.form_widget.rowCount()
                        Workbook.form_widget.insertRow(row)
                        for column, stuff in enumerate(row_data):
                            item = QTableWidgetItem(stuff)
                            Workbook.form_widget.setItem(row, column, item)
                    if Workbook.form_widget.rowCount() < 26:
                        Workbook.form_widget.nrows = Workbook.form_widget.rowCount(
                        )
                        Workbook.form_widget.setRowCount(26)
                Workbook.form_widget.check_change = True
            for w in range(self.work_books):
                try:
                    remove('your_csv_file{0:d}.csv'.format(w))
                except:
                    pass

        return Sheets(self.work_booksList, paths)

    def validate_sheet(self):
        ''' validates the workbook table if contains bad values calls message box

        :return: None
        '''
        Bad_val = []
        ID_col = []
        flag = 'NoDuplicateID'
        cur_workbook = self.Tab_widget.currentIndex()
        ncols = self.work_booksList[cur_workbook].form_widget.ncols
        nrows = self.work_booksList[cur_workbook].form_widget.nrows
        for i in range(0, ncols):
            for j in range(0, nrows):
                if self.work_booksList[cur_workbook].form_widget.item(
                        j, i) is not None:
                    if (self.work_booksList[cur_workbook].form_widget.item(
                            j, i).text()).replace('.',
                                                  '').isnumeric() == False:
                        Bad_val.append([i, j])
                    elif i == 0:
                        ID_col.append(
                            self.work_booksList[cur_workbook].form_widget.item(
                                j, i).text())
        #checking duplicate IDs
        if len(ID_col) > len(set(ID_col)):
            flag = 'DuplicateID'
        if len(Bad_val) > 0 or flag == 'DuplicateID':
            self.work_booksList[cur_workbook].form_widget.messageBox(
                Bad_val, flag)

    def submit_sheet(self):
        ''' creates the text file of each row of workbook containg the data of that row

        :return: None
        '''
        cur_workbookIndex = self.Tab_widget.currentIndex()
        cur_workbookTitle = self.Tab_widget.tabText(cur_workbookIndex)
        ncols = self.work_booksList[cur_workbookIndex].form_widget.ncols
        nrows = self.work_booksList[cur_workbookIndex].form_widget.nrows
        Dictonary = {}
        for i in range(0, nrows):
            for j in range(0, ncols):
                if self.work_booksList[cur_workbookIndex].form_widget.item(
                        i, j) is not None:
                    Dictonary[
                        self.work_booksList[cur_workbookIndex].form_widget.
                        horizontalHeaderItem(j).text()] = self.work_booksList[
                            cur_workbookIndex].form_widget.item(i, j).text()
            if self.work_booksList[cur_workbookIndex].form_widget.item(
                    i, 0) is not None:
                with open(
                        '{0:s}_{1:s}.txt'.format(
                            cur_workbookTitle,
                            self.work_booksList[cur_workbookIndex].form_widget.
                            item(i, 0).text()), 'w') as file:
                    file.write(
                        dumps(Dictonary).replace('{', '').replace('}', ''))
                Dictonary.clear()

    def quit_app(self):
        ''' Quits the window and closes the app

        :return: None
        '''
        qApp.quit()
예제 #17
0
class TfrmBase(QMainWindow, TScreenStates):

    recordCount = 0

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

        self.FOnStateChange = self.onStateChange
        self.activeState = self.ssInactive
        self._defaultSettings()
        self._createWidgets()
        self._setEvents()

    def _defaultSettings(self):
        self.setObjectName("frmBase")
        self.resize(640, 480)
        self.setMinimumSize(QSize(640, 480))

    def _createWidgets(self):
        self._createLayout()
        self._createMenus()
        self._createToolBar()
        self._createStatusBar()
        self._createPages()
        self._setLayouts()

    def _createLayout(self):
        self.clientArea = QWidget()
        self.clientArea.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.clientArea.setMinimumSize(QSize(640, 400))
        self.clientArea.setBaseSize(QSize(640, 400))
        self.clientArea.setLayoutDirection(Qt.LeftToRight)
        self.clientArea.setObjectName("clientArea")
        self.gridLayout = QGridLayout(self.clientArea)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName("gridLayout")

    def _createMenus(self):
        # Create a Menu Bar
        self.mnMenu = self.menuBar()
        self.mnMenu.setObjectName("mnMenu")
        # Create all Top Menus
        self.mnApp = QMenu('&Aplicação')
        self.mnApp.setObjectName('mnApp')
        self.mnOpe = QMenu('&Operação')
        self.mnOpe.setObjectName("mnOperations")
        self.mnNav = QMenu('&Navegação')
        self.mnNav.setObjectName("mnNav")
        # Set Menus to MenuBar
        self.mnMenu.addMenu(self.mnNav)
        self.mnMenu.addMenu(self.mnOpe)
        self.mnMenu.addMenu(self.mnApp)
        # Crealte all Actions to Application Menu
        self._createAppActions()
        self._createOpeActions()
        self._setMenuActions()
        self.mnMenu.addAction(self.mnApp.menuAction())
        self.mnMenu.addAction(self.mnOpe.menuAction())
        self.mnMenu.addAction(self.mnNav.menuAction())
        self._settingActionsEvents()

    def _createAppActions(self):
        # Exit Program Action
        self.acExit = QAction(
            self.getIcon("./resources/exit.ico", QSize(32, 32)), '&Sair')
        self.acExit.setObjectName("acExit")
        self.acExit.setShortcut('Ctrl+Q')
        self.acExit.setStatusTip('Finalizar o Programa')
        self.acExit.triggered.connect(self.closeApp)

    def _createOpeActions(self):
        # Search Action
        self.acSearch = QAction(
            self.getIcon("./resources/Search.ico", QSize(32, 32)),
            '&Pesquisar')
        self.acSearch.setObjectName("acSearch")
        self.acSearch.setShortcut('F5,Ctrl+P')
        self.acSearch.setStatusTip(
            'Preenche o Filtro para Selecionar Registros')
        # List Action
        self.acList = QAction(
            self.getIcon("./resources/list.ico", QSize(32, 32)), '&Listar')
        self.acList.setShortcut('Ctrl+L')
        self.acList.setStatusTip('Listar todos os Registros')
        self.acList.setObjectName("acList")
        # Insert Action
        self.acInsert = QAction(
            self.getIcon("./resources/db_add.ico", QSize(32, 32)), '&Inserir')
        self.acInsert.setShortcut('F2,Ins')
        self.acInsert.setStatusTip('Incluir Novo Registros')
        self.acInsert.setObjectName("acInsert")
        # Update Action
        self.acUpdate = QAction(
            self.getIcon("./resources/db_update.ico", QSize(32, 32)),
            '&Editar')
        self.acUpdate.setShortcut('Ctrl+U')
        self.acUpdate.setStatusTip('Editar o Registro Atual')
        self.acUpdate.setObjectName("acUpdate")
        # Delete Action
        self.acDelete = QAction(
            self.getIcon("./resources/db_remove.ico", QSize(32, 32)),
            '&Excluir')
        self.acDelete.setShortcut('Ctrl+Del')
        self.acDelete.setStatusTip('Exclui o Registro Atual')
        self.acDelete.setObjectName("acDelete")
        # Save Action
        self.acSave = QAction(
            self.getIcon("./resources/db_commit.ico", QSize(32, 32)),
            '&Salvar')
        self.acSave.setShortcut('F10,Ctrl+S')
        self.acSave.setStatusTip('Salva as Alterações do Registro')
        self.acSave.setObjectName("acSave")
        # Cancel Action
        self.acCancel = QAction(
            self.getIcon("./resources/cancel.ico", QSize(32, 32)), '&Cancelar')
        self.acCancel.setShortcut('Esc')
        self.acCancel.setStatusTip('Cancela as Alterações do Registro')
        self.acCancel.setObjectName("acCancel")
        # First Action
        self.acFirst = QAction(
            self.getIcon("./resources/start.ico", QSize(32, 32)), '&Início')
        self.acFirst.setShortcut('Ctrl+Left')
        self.acFirst.setStatusTip('Vai para o Primeiro Registro')
        self.acFirst.setObjectName("acFirst")
        # Prior Action
        self.acPrior = QAction(
            self.getIcon("./resources/left.ico", QSize(32, 32)), '&Anterior')
        self.acPrior.setShortcut('Left')
        self.acPrior.setStatusTip('Vai para o Registro Anterior')
        self.acPrior.setObjectName("acPrior")
        # Next Action
        self.acNext = QAction(
            self.getIcon("./resources/right.ico", QSize(32, 32)), '&Próximo')
        self.acNext.setShortcut('Right')
        self.acNext.setStatusTip('Vai para o Próximo Registro')
        self.acNext.setObjectName("acNext")
        # Last Action
        self.acLast = QAction(
            self.getIcon("./resources/end.ico", QSize(32, 32)), '&Último')
        self.acLast.setShortcut('Ctrl+Right')
        self.acLast.setStatusTip('Vai para o Último Registro')
        self.acLast.setObjectName("acLast")
        # Form Title Action
        self.dcTitle = QAction()
        font = QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.dcTitle.setFont(font)
        self.dcTitle.setObjectName("dcTitle")

    def getIcon(self, res: str, size: QSize) -> QIcon:
        icon = QIcon()
        icon.addPixmap(
            QPixmap(res).scaled(size.width(), size.height(),
                                Qt.KeepAspectRatio), QIcon.Active, QIcon.On)
        return icon

    def _setMenuActions(self):
        # Set Menu Application Actions
        self.mnApp.addAction(self.acExit)
        # Set Menu Operations Actions
        self.mnOpe.addAction(self.acSearch)
        self.mnOpe.addAction(self.acList)
        self.mnOpe.addSeparator()
        self.mnOpe.addAction(self.acInsert)
        self.mnOpe.addAction(self.acUpdate)
        self.mnOpe.addAction(self.acDelete)
        self.mnOpe.addSeparator()
        self.mnOpe.addAction(self.acSave)
        self.mnOpe.addAction(self.acCancel)
        # Set Menu Navigation Actions
        self.mnNav.addAction(self.acFirst)
        self.mnNav.addAction(self.acPrior)
        self.mnNav.addAction(self.acNext)
        self.mnNav.addAction(self.acLast)

    def _settingActionsEvents(self):
        # Set Menu Operations Trigger onClick
        self.acSearch.triggered.connect(
            lambda: self.setFormStatus(self.ssSearch))
        self.acList.triggered.connect(
            lambda: self.setFormStatus(self.ssSearchAll))
        self.acInsert.triggered.connect(
            lambda: self.setFormStatus(self.ssInsert))
        self.acUpdate.triggered.connect(
            lambda: self.setFormStatus(self.ssUpdate))
        self.acDelete.triggered.connect(
            lambda: self.setFormStatus(self.ssDelete))
        self.acSave.triggered.connect(lambda: self.setFormStatus(self.ssPost))
        self.acCancel.triggered.connect(
            lambda: self.setFormStatus(self.ssCancel))
        # Set Menu Navigation Trigger onClick
        self.acFirst.triggered.connect(
            lambda: self.setFormStatus(self.ssFirst))
        self.acPrior.triggered.connect(
            lambda: self.setFormStatus(self.ssPrior))
        self.acNext.triggered.connect(lambda: self.setFormStatus(self.ssNext))
        self.acLast.triggered.connect(lambda: self.setFormStatus(self.ssLast))

    def _createToolBar(self):
        # Create a tbActions ToolBar
        self.tbActions = QToolBar()
        self.tbActions.setMinimumSize(QSize(300, 34))
        self.tbActions.setMaximumSize(QSize(16777215, 34))
        self.tbActions.setBaseSize(QSize(300, 34))
        self.tbActions.setAcceptDrops(False)
        self.tbActions.setToolTipDuration(3)
        self.tbActions.setAllowedAreas(Qt.TopToolBarArea)
        self.tbActions.setObjectName("tbActions")
        self.addToolBar(Qt.TopToolBarArea, self.tbActions)
        # Create a tbTitle ToolBar
        self.tbTitle = QToolBar()
        self.tbTitle.setMinimumSize(QSize(340, 34))
        self.tbTitle.setMaximumSize(QSize(16777215, 34))
        self.tbTitle.setBaseSize(QSize(341, 34))
        self.tbTitle.setAllowedAreas(Qt.TopToolBarArea)
        self.tbTitle.setToolButtonStyle(Qt.ToolButtonTextOnly)
        self.tbTitle.setFloatable(False)
        self.tbTitle.setObjectName("tbTitle")
        # self.tbTitle.setLabelAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.addToolBar(Qt.TopToolBarArea, self.tbTitle)
        # Call Add Actions to ToolBar
        self._setToolBarActions()

    def _setToolBarActions(self):
        # Set ToolBar Actions
        self.tbActions.addAction(self.acSearch)
        self.tbActions.addAction(self.acInsert)
        self.tbActions.addAction(self.acUpdate)
        self.tbActions.addAction(self.acDelete)
        self.tbActions.addSeparator()
        self.tbActions.addAction(self.acSave)
        self.tbActions.addAction(self.acExit)
        self.tbTitle.addAction(self.dcTitle)

    def _createStatusBar(self):
        self.sbStatus = QStatusBar()
        self.sbStatus.setMaximumHeight(24)
        self.sbStatus.setObjectName("sbStatus")
        self.sbStatus.setStyleSheet("""
            .QLabel {
                background-color: #FFFFFF;
                color: #000000;
            }
        """)
        self.lbStatus = QLabel(self.sbStatus)
        self.lbStatus.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.lbStatus.setText('Inactive')
        self.lbStatus.setMinimumSize(QSize(130, 15))
        self.lbStatus.setFrameShape(QFrame.Panel)
        self.lbStatus.setFrameShadow(QFrame.Sunken)
        self.sbStatus.addPermanentWidget(self.lbStatus)
        self.setStatusBar(self.sbStatus)

    def _createPages(self):
        self.tabMain = QTabWidget(self.clientArea)
        self.tabMain.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.tabMain.setTabPosition(QTabWidget.South)
        self.tabMain.setObjectName("tabMain")
        self.pgList = QWidget(self.tabMain)
        self.pgList.setObjectName("pgList")
        self.pgDetail = QWidget(self.tabMain)
        self.pgDetail.setObjectName("pgDetail")
        self.tabMain.addTab(self.pgList, "")
        self.tabMain.addTab(self.pgDetail, "")
        self._createPageListContent()

    def _createPageListContent(self):
        self.treeWidget = QTreeWidget(self.pgList)
        self.treeWidget.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.treeWidget.setFrameShape(QFrame.NoFrame)
        self.treeWidget.setFrameShadow(QFrame.Plain)
        self.treeWidget.setColumnCount(3)
        self.treeWidget.setObjectName("treeWidget")
        self.treeWidget.headerItem().setText(0, "Campo")
        self.treeWidget.headerItem().setText(1, "Campo")
        self.treeWidget.headerItem().setText(2, "Campo")
        self.treeWidget.setGeometry(QRect(0, 0, 640, 370))
        self.treeWidget.setMinimumSize(QSize(640, 370))
        self.tabMain.setCurrentIndex(0)

    def _setLayouts(self):
        self.gridLayout.addWidget(self.tabMain, 0,
                                  Qt.AlignBottom | Qt.AlignRight, 1, 1)
        self.setCentralWidget(self.clientArea)

    def translateForm(self):
        self._translate = QCoreApplication.translate
        self.setWindowTitle(
            self._translate("TfrmBase", "Tela de Básica de Cadastros"))
        self.mnApp.setTitle(self._translate("TfrmBase", "Aplicação"))
        self.mnOpe.setTitle(self._translate("TfrmBase", "Operações"))
        self.mnNav.setTitle(self._translate("TfrmBase", "Navegação"))
        self.sbStatus.setToolTip(self._translate("TfrmBase",
                                                 "Barra de Status"))
        self.tbActions.setWindowTitle(
            self._translate("TfrmBase", "Ferramentas"))
        self.tbActions.setToolTip(
            self._translate("TfrmBase", "Barra de Ferramentas"))
        self.tbTitle.setWindowTitle(self._translate("TfrmBase", "Descrição"))
        self.acExit.setText(self._translate("TfrmBase", "&Sair"))
        self.acExit.setToolTip(self._translate("TfrmBase", "Sair do Programa"))
        self.acSearch.setText(self._translate("TfrmBase", "&Pesquisar"))
        self.acSearch.setStatusTip(
            self._translate("TfrmBase", "Procurar Por um Registro"))
        self.acList.setText(self._translate("TfrmBase", "&Listar Todos"))
        self.acList.setStatusTip(
            self._translate("TfrmBase", "Lista todos os Registros"))
        self.acInsert.setText(self._translate("TfrmBase", "&Inserir"))
        self.acInsert.setStatusTip(
            self._translate("TfrmBase", "Adicionar Registro"))
        self.acUpdate.setText(self._translate("TfrmBase", "&Editar"))
        self.acUpdate.setStatusTip(
            self._translate("TfrmBase", "Editar Registro"))
        self.acDelete.setText(self._translate("TfrmBase", "E&xcluir"))
        self.acDelete.setStatusTip(
            self._translate("TfrmBase", "Excluir Registro"))
        self.acSave.setText(self._translate("TfrmBase", "&Salvar"))
        self.acSave.setToolTip(self._translate("TfrmBase", "Salvar Registro"))
        self.acCancel.setText(self._translate("TfrmBase", "&Cancelar"))
        self.acCancel.setToolTip(
            self._translate("TfrmBase", "Cencelar Alterações"))
        self.dcTitle.setText(
            self._translate("TfrmBase", "Título da Tela de Cadastros"))
        self.dcTitle.setToolTip(
            self._translate("TfrmBase", "Título da Tela de Cadastros"))
        self.tabMain.setTabText(
            self.tabMain.indexOf(self.pgList),
            self._translate("TfrmBase", "Lista dos Registros"))
        self.tabMain.setTabToolTip(
            self.tabMain.indexOf(self.pgList),
            self._translate("TfrmBase", "Listagem das Ferramentas"))
        self.tabMain.setTabText(
            self.tabMain.indexOf(self.pgDetail),
            self._translate("TfrmBase", "Detalhes do Registro Selecionando"))

    @property
    def activeState(self):
        return self._activeValue

    @property
    def activeStateColor(self):
        return self.activeValue['FG']

    @property
    def activeStateBackgroud(self):
        return self.activeValue['BG']

    @activeState.setter  # Seta a Propriedade _activeState
    def activeState(self, value: int):
        self.workValue = value
        self._activeState = value

    def setScreenState(self, stt: int):
        self.acExit.setEnabled(self.inBrowse(stt))
        # Set Menu Operations Actions
        self.acSearch.setEnabled((self.inBrowse(stt)
                                  or (self.recordCount == 0)))
        self.acList.setEnabled((self.inBrowse(stt) or (self.recordCount == 0)))
        self.acInsert.setEnabled(self.inBrowse(stt))
        self.acUpdate.setEnabled((self.inBrowse(stt)
                                  and (self.recordCount > 0)))
        self.acDelete.setEnabled((self.inBrowse(stt)
                                  and (self.recordCount > 0)))
        self.acSave.setEnabled(self.inUpdate(stt))
        self.acCancel.setEnabled(self.inUpdate(stt))
        # Set Menu Navigation Actions
        self.acFirst.setEnabled((self.inBrowse(stt)
                                 and (self.recordCount > 0)))
        self.acPrior.setEnabled((self.inBrowse(stt)
                                 and (self.recordCount > 0)))
        self.acNext.setEnabled((self.inBrowse(stt) and (self.recordCount > 0)))
        self.acLast.setEnabled((self.inBrowse(stt) and (self.recordCount > 0)))
        # Set tab Main if state in Browse enabled
        self.tabMain.setEnabled(self.inBrowse(stt))

    def _layoutWidgets(self):
        return (self.frmLayout.itemAt(i)
                for i in range(self.frmLayout.count()))

    def _getAllFields(self):
        arrFields = []
        for w in self._layoutWidgets():
            if (not (isinstance(w, QLabel))):
                arrFields.append(w)
        return arrFields

    def setEnableFields(self, enable: bool = True):
        # Enable All Fields
        for controls in self._layoutWidgets():
            QWidget(controls).setEnabled(enable)

    def clearFields(self):
        # cliar content of all fileds
        for controls in self._getAllFields():
            QWidget(controls).setText('')

    def setColorFields(self):
        # cliar content of all fileds
        style = ".QWidget { backgroud-color: " + self.activeStateBackgroud + "; }"
        for controls in self._getAllFields():
            QWidget(controls).setStyle(style)

    def showDataDetails(self):
        # move data of selected record to fileds
        if (self.tabMain.currentIndex() == 0):
            self.tabMain.setCurrentIndex(1)

    def filterRecord(self):
        raise NotImplementedError(500)

    def getFirstRecord(self):
        raise NotImplementedError(500)

    def getPriorRecord(self):
        raise NotImplementedError(500)

    def getNextRecord(self):
        raise NotImplementedError(500)

    def getLastRecord(self):
        raise NotImplementedError(500)

    def insertRecord(self):
        raise NotImplementedError(500)

    def deleteRecord(self):
        raise NotImplementedError(500)

    def updateRecord(self):
        raise NotImplementedError(500)

    def postRecord(self):
        raise NotImplementedError(500)

    def execOpertations(self, state: int):
        if ((state == self.ssFilter) or (state == self.ssSearchAll)):
            self.filterRecord()
        elif (state == self.ssFirst):
            self.getFirstRecord()
        elif (state == self.ssPrior):
            self.getPriorRecord()
        elif (state == self.ssNext):
            self.getNextRecord()
        elif (state == self.ssLast):
            self.getLastRecord()
        elif (state == self.ssInsert):
            self.insertRecord()
        elif (state == self.ssDelete):
            self.deleteRecord()
        elif (state == self.ssUpdate):
            self.updateRecord()
        elif (state == self.ssPost):
            self.postRecord()
        else:
            raise NotImplementedError(401, 'Operação não suportada')

    @pyqtSlot(int)
    def setFormStatus(self, state: int):
        if ((state == self.ssSearch) and (self.activeState != state)):
            self.clearFields()
            self.setColorFields()
            self.showDataDetails()

        if (self.activeState != state):
            self.activeState = state
            if (state == self.ssCancel):
                self.activeState = self.ssBrowse

    @pyqtSlot(int, int, dict, str)
    def onStateChange(self,
                      NewState: int,
                      OldState: int,
                      Result: dict = {},
                      Err: str = ''):
        try:
            # show screen state on status bar
            state = self.getStateProperties(NewState)
            style = '.QLabel { background-color: ' + state[
                'BG'] + '; color: ' + state['FG'] + '; }'
            self.sbStatus.setStyleSheet(style)
            self.lbStatus.setText(state['Descr'])

            # call operation into child screen
            self.execOpertations(NewState)
            # change buttons states
            self.setScreenState(NewState)
            # set result status code and result satatus Message
            self.setResultStatusCode = 200
            self.setResultStatusMessage = ''
        except Exception as e:
            self.ResultStatusCode = 200
            self.ResultStatusMessage = str(e)
            QMessageBox.critical(self, self.windowTitle(),
                                 self.ResultStatusMessage)
        return self.result

    @pyqtSlot()
    def tabMainChanged(self):
        self.sbStatus.showMessage('TabMain change tabIndex to (' +
                                  str(self.tabMain.currentIndex()) + ')!')
        if (self.tabMain.currentIndex() == 1):
            self.showDataDetails()

    @pyqtSlot()
    def InsertData(self):
        # self.sbStatus.showMessage('Prepare to insert data....')
        pass

    def _setEvents(self):
        self.tabMain.blockSignals(
            True)  # just for not showing the initial message
        self.tabMain.currentChanged.connect(self.tabMainChanged)  # changed!
        self.tabMain.blockSignals(False)  # wait signals now

    @pyqtSlot()
    def closeApp(self):
        self.close()
예제 #18
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.fnames = []  # list of file names to be converted
        self.office_listener_started = False

        self.parse_cla()

        addQPB = QPushButton(self.tr('Add'))
        delQPB = QPushButton(self.tr('Delete'))
        clearQPB = QPushButton(self.tr('Clear'))
        vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None)

        self.filesList = utils.FilesList()
        self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection)
        hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1)

        outputQL = QLabel(self.tr('Output folder:'))
        self.toQLE = QLineEdit()
        self.toQLE.setReadOnly(True)
        self.toQTB = QToolButton()
        self.toQTB.setText('...')
        hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB)

        self.audiovideo_tab = AudioVideoTab(self)
        self.image_tab = ImageTab(self)
        self.document_tab = DocumentTab(self)

        self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab]
        tab_names = [self.tr('Audio/Video'), self.tr('Images'),
                     self.tr('Documents')]

        self.tabWidget = QTabWidget()
        for num, tab in enumerate(tab_names):
            self.tabWidget.addTab(self.tabs[num], tab)
        self.tabWidget.setCurrentIndex(0)

        self.origQCB = QCheckBox(
                self.tr('Save each file in the same\nfolder as input file'))
        self.deleteQCB = QCheckBox(self.tr('Delete original'))
        convertQPB = QPushButton(self.tr('&Convert'))

        hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None)
        hlayout4 = utils.add_to_layout('h', None, convertQPB)
        final_layout = utils.add_to_layout(
                'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4)

        self.dependenciesQL = QLabel()
        self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1)

        widget = QWidget()
        widget.setLayout(final_layout)
        self.setCentralWidget(widget)

        openAction = utils.create_action(
                self, self.tr('Open'), QKeySequence.Open, None,
                self.tr('Open a file'), self.filesList_add
                )
        convertAction = utils.create_action(
                self, self.tr('Convert'), 'Ctrl+C', None,
                self.tr('Convert files'), self.start_conversion
                )
        quitAction = utils.create_action(
                self, self.tr('Quit'), 'Ctrl+Q', None,
                self.tr('Quit'), self.close
                )
        edit_presetsAction = utils.create_action(
                self, self.tr('Edit Presets'), 'Ctrl+P', None,
                self.tr('Edit Presets'), self.open_dialog_presets
                )
        importAction = utils.create_action(
                self, self.tr('Import'), None, None,
                self.tr('Import presets'), self.import_presets
                )
        exportAction = utils.create_action(
                self, self.tr('Export'), None, None,
                self.tr('Export presets'), self.export_presets
                )
        resetAction = utils.create_action(
                self, self.tr('Reset'), None, None,
                self.tr('Reset presets'), self.reset_presets
                )
        syncAction = utils.create_action(
                self, self.tr('Synchronize'), None, None,
                self.tr('Synchronize presets'), self.sync_presets
                )
        removeoldAction = utils.create_action(
                self, self.tr('Remove old'), None, None,
                self.tr('Remove old presets'), self.removeold_presets
                )
        clearallAction = utils.create_action(
                self, self.tr('Clear All'), None, None,
                self.tr('Clear form'), self.clear_all
                )
        preferencesAction = utils.create_action(
                self, self.tr('Preferences'), 'Alt+Ctrl+P',
                None, self.tr('Preferences'), self.open_dialog_preferences
                )
        trackerAction = utils.create_action(
                self, 'Issue tracker', None, None, None,
                lambda: webbrowser.open(
                    "https://github.com/Ilias95/FF-Multi-Converter/issues")
                )
        wikiAction = utils.create_action(
                self, 'Wiki', None, None, None,
                lambda: webbrowser.open(
                    "https://github.com/Ilias95/FF-Multi-Converter/wiki")
                )
        ffmpegdocAction = utils.create_action(
                self, 'FFmpeg ' + self.tr('documentation'), None, None, None,
                lambda: webbrowser.open(
                    "https://www.ffmpeg.org/documentation.html")
                )
        imagemagickdocAction = utils.create_action(
                self, 'ImageMagick ' + self.tr('documentation'), None, None,
                None, lambda: webbrowser.open(
                    "http://www.imagemagick.org/script/convert.php")
                )
        aboutAction = utils.create_action(
                self, self.tr('About'), 'Ctrl+?', None,
                self.tr('About'), self.open_dialog_about
                )

        fileMenu = self.menuBar().addMenu(self.tr('File'))
        editMenu = self.menuBar().addMenu(self.tr('Edit'))
        presetsMenu = self.menuBar().addMenu(self.tr('Presets'))
        helpMenu = self.menuBar().addMenu(self.tr('Help'))

        utils.add_actions(
                fileMenu, [openAction, convertAction, None, quitAction])
        utils.add_actions(
                presetsMenu,
                [edit_presetsAction, importAction, exportAction, resetAction,
                 None, syncAction, removeoldAction]
                )
        utils.add_actions(editMenu, [clearallAction, None, preferencesAction])
        utils.add_actions(
                helpMenu,
                [trackerAction, wikiAction, None, ffmpegdocAction,
                imagemagickdocAction, None, aboutAction]
                )

        self.filesList.dropped.connect(self.filesList_add_dragged)
        addQPB.clicked.connect(self.filesList_add)
        delQPB.clicked.connect(self.filesList_delete)
        clearQPB.clicked.connect(self.filesList_clear)
        self.tabWidget.currentChanged.connect(
                lambda: self.tabs[0].moreQPB.setChecked(False))
        self.origQCB.toggled.connect(
                lambda: self.toQLE.setEnabled(not self.origQCB.isChecked()))
        self.toQTB.clicked.connect(self.get_output_folder)
        convertQPB.clicked.connect(convertAction.triggered)

        del_shortcut = QShortcut(self)
        del_shortcut.setKey(Qt.Key_Delete)
        del_shortcut.activated.connect(self.filesList_delete)

        self.setWindowTitle('FF Multi Converter')

        self.load_settings()
        self.check_for_dependencies()

        self.audiovideo_tab.set_default_command()
        self.image_tab.set_default_command()
        self.toQLE.setText(self.default_output)

        self.filesList_update()


    def parse_cla(self):
        """Parse command line arguments."""
        for i in QCoreApplication.arguments()[1:]:
            i = os.path.abspath(i)
            if os.path.isfile(i):
                self.fnames.append(i)
            else:
                print("ffmulticonverter: {0}: Not a file".format(i))

    def check_for_dependencies(self):
        """
        Check if each one of the program dependencies are installed and
        update self.dependenciesQL with the appropriate message.
        """
        if not utils.is_installed(self.ffmpeg_path):
            self.ffmpeg_path = utils.is_installed('ffmpeg')
            QSettings().setValue('ffmpeg_path', self.ffmpeg_path)
        self.unoconv = utils.is_installed('unoconv')
        self.imagemagick = utils.is_installed('convert')

        missing = []
        if not self.ffmpeg_path:
            missing.append('ffmpeg')
        if not self.unoconv:
            missing.append('unoconv')
        if not self.imagemagick:
            missing.append('imagemagick')

        if missing:
            missing = ', '.join(missing)
            status = self.tr('Missing dependencies:') + ' ' + missing
            self.dependenciesQL.setText(status)

    def load_settings(self):
        settings = QSettings()

        self.overwrite_existing = settings.value('overwrite_existing', type=bool)
        self.default_output = settings.value('default_output', type=str)
        self.prefix = settings.value('prefix', type=str)
        self.suffix = settings.value('suffix', type=str)
        self.ffmpeg_path = settings.value('ffmpeg_path', type=str)
        self.default_command = (settings.value('default_command', type=str) or
                config.default_ffmpeg_cmd)
        # type=list won't work for some reason
        extraformats_video = (settings.value('extraformats_video') or [])
        videocodecs = (settings.value('videocodecs') or config.video_codecs)
        audiocodecs = (settings.value('audiocodecs') or config.audio_codecs)
        self.default_command_image = (settings.value('default_command_image',
                type=str) or
                config.default_imagemagick_cmd)
        extraformats_image = (settings.value('extraformats_image') or [])
        extraformats_document = (settings.value('extraformats_document') or [])

        self.audiovideo_tab.fill_video_comboboxes(videocodecs,
                audiocodecs, extraformats_video)
        self.image_tab.fill_extension_combobox(extraformats_image)
        self.document_tab.fill_extension_combobox(extraformats_document)

    def get_current_tab(self):
        for i in self.tabs:
            if self.tabs.index(i) == self.tabWidget.currentIndex():
                return i

    def filesList_update(self):
        self.filesList.clear()
        for i in self.fnames:
            self.filesList.addItem(i)

    def filesList_add(self):
        filters  = 'All Files (*);;'
        filters += 'Audio/Video Files (*.{});;'.format(
                ' *.'.join(self.audiovideo_tab.formats))
        filters += 'Image Files (*.{});;'.format(
                ' *.'.join(self.image_tab.formats + self.image_tab.extra_img))
        filters += 'Document Files (*.{})'.format(
                ' *.'.join(self.document_tab.formats))

        fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' +
                self.tr('Choose File'), config.home, filters,
                options=QFileDialog.HideNameFilterDetails)[0]

        if fnames:
            for i in fnames:
                if not i in self.fnames:
                    self.fnames.append(i)
            self.filesList_update()

    def filesList_add_dragged(self, links):
        for path in links:
            if os.path.isfile(path) and not path in self.fnames:
                self.fnames.append(path)
        self.filesList_update()

    def filesList_delete(self):
        items = self.filesList.selectedItems()
        if items:
            for i in items:
                self.fnames.remove(i.text())
            self.filesList_update()

    def filesList_clear(self):
        self.fnames = []
        self.filesList_update()

    def clear_all(self):
        """Clears or sets to default the values of all graphical widgets."""
        self.toQLE.clear()
        self.origQCB.setChecked(False)
        self.deleteQCB.setChecked(False)
        self.filesList_clear()

        self.audiovideo_tab.clear()
        self.image_tab.clear()

    def get_output_folder(self):
        if self.toQLE.isEnabled():
            output = QFileDialog.getExistingDirectory(
                    self, 'FF Multi Converter - ' +
                    self.tr('Choose output destination'),
                    config.home)
            if output:
                self.toQLE.setText(output)

    def import_presets(self):
        presets_dlgs.ShowPresets().import_presets()

    def export_presets(self):
        presets_dlgs.ShowPresets().export_presets()

    def reset_presets(self):
        presets_dlgs.ShowPresets().reset()

    def sync_presets(self):
        presets_dlgs.ShowPresets().synchronize()

    def removeold_presets(self):
        presets_dlgs.ShowPresets().remove_old()

    def ok_to_continue(self):
        """
        Check if everything is ok to continue with conversion.

        Check if:
        - At least one file has given for conversion.
        - An output folder has given.
        - Output folder exists.

        Return False if an error arises, else True.
        """
        try:
            if not self.fnames:
                raise ValidationError(
                        self.tr('You must add at least one file to convert!'))
            elif not self.origQCB.isChecked() and not self.toQLE.text():
                raise ValidationError(
                        self.tr('You must choose an output folder!'))
            elif (not self.origQCB.isChecked() and
                  not os.path.exists(self.toQLE.text())):
                raise ValidationError(self.tr('Output folder does not exists!'))
            if not self.get_current_tab().ok_to_continue():
                return False
            return True

        except ValidationError as e:
            QMessageBox.warning(
                    self, 'FF Multi Converter - ' + self.tr('Error!'), str(e))
            return False

    def start_conversion(self):
        """
        Extract the appropriate information from GUI and call the
        Progress dialog with the suitable argumens.
        """
        if not self.ok_to_continue():
            return

        tab = self.get_current_tab()
        ext_to = '.' + tab.extQCB.currentText()

        if tab.name == 'Documents' and not self.office_listener_started:
            utils.start_office_listener()
            self.office_listener_started = True

        _list = utils.create_paths_list(
                self.fnames, ext_to, self.prefix, self.suffix,
                self.toQLE.text(), self.origQCB.isChecked(),
                self.overwrite_existing
                )

        dialog = progress.Progress(
                _list, tab, self.deleteQCB.isChecked(), self)
        dialog.show()

    def open_dialog_preferences(self):
        """Open the preferences dialog."""
        dialog = preferences_dlg.Preferences(self)
        if dialog.exec_():
            self.load_settings()

    def open_dialog_presets(self):
        """Open the presets dialog."""
        dialog = presets_dlgs.ShowPresets(self)
        dialog.exec_()

    def open_dialog_about(self):
        """Call the about dialog with the appropriate values."""
        msg = self.tr('Convert among several file types to other formats')
        msg = textwrap.fill(msg, 54).replace('\n', '<br>')
        text = '''<b> FF Multi Converter {0} </b>
                 <p>{1}
                 <p><a href="{2}">FF Multi Converter - Home Page</a>
                 <p>Copyright &copy; 2011-2016 {3}
                 <br>License: {4}
                 <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\
                 .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__,
                         ffmc.__license__, platform.python_version()[:5],
                         QT_VERSION_STR, PYQT_VERSION_STR, platform.system())
        image = ':/ffmulticonverter.png'
        authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__)
        authors += 'Contributors:\nPanagiotis Mavrogiorgos'
        translators = []
        for i in config.translators:
            translators.append('{0}\n     {1}'.format(i[0], i[1]))
        translators = '\n\n'.join(translators)

        dialog = about_dlg.AboutDialog(text, image, authors, translators, self)
        dialog.exec_()
예제 #19
0
class Main_UI(QMainWindow):
    # Main Variables in this class.
    def __init__(self, auth_info):
        super(Main_UI, self).__init__()
        self.auth_info = auth_info
        self.exp_Class = auth_info['Class']
        self.exp_username = auth_info['username']
        self.exp_password = auth_info['password']
        self.exp_dbname = auth_info['DBName']
        self.db_conn = SQL.connect('localhost', auth_info['username'],
                                   auth_info['password'], auth_info['DBName'])
        self.full_width = QApplication.primaryScreen().size().width() - 15
        self.full_height = QApplication.primaryScreen().size().height() - 68
        self.Main_Grid = QGridLayout()
        self.toolbar = QToolBar()
        self.tabwidget = QTabWidget()
        self.win_icon = "Resources/sm_logo_icon.ico"
        self.win_title = "Sales Manager V1.0 | %s - %s" % (self.exp_Class,
                                                           self.exp_username)
        self.table_label = {
            'clients':
            ['ID', 'Name', 'Email', 'Username', 'Password', 'Number Phone'],
            'products':
            ['ID', 'Product Name', 'Quantity', 'Unit Price', 'Product Code'],
            'requests': [
                'ID', 'Client', 'Product Name', 'Quantity', 'Request Date',
                'Status'
            ]
        }
        if self.exp_Class == "Importer":
            self.Importer_UI()
        elif self.exp_Class == "Exporter":
            self.Exporter_UI()

#Eporter Interface

    def Exporter_UI(self):
        self.setGeometry(0, 0, self.full_width, self.full_height)
        self.setWindowTitle(self.win_title)
        self.setWindowIcon(QIcon(self.win_icon))
        self.toolbar.setMovable(False)
        self.toolbar.setIconSize(QSize(32, 32))
        # Tables in Exporter Interface
        # Table_1 - clients
        self.table_1 = QTableWidget()
        self.Hheader_1 = self.table_1.horizontalHeader()
        self.Vheader_1 = self.table_1.verticalHeader()
        self.table_1.setAlternatingRowColors(True)
        self.table_1.setColumnCount(6)
        self.Hheader_1.setCascadingSectionResizes(False)
        self.Hheader_1.setSortIndicatorShown(False)
        self.Hheader_1.setStretchLastSection(True)
        self.Vheader_1.setVisible(False)
        self.Vheader_1.setCascadingSectionResizes(False)
        self.Vheader_1.setStretchLastSection(False)
        self.table_1.setHorizontalHeaderLabels(self.table_label['clients'])
        # Table_2 - products
        self.table_2 = QTableWidget()
        self.Hheader_2 = self.table_2.horizontalHeader()
        self.Vheader_2 = self.table_2.verticalHeader()
        self.table_2.setAlternatingRowColors(True)
        self.table_2.setColumnCount(5)
        self.Hheader_2.setCascadingSectionResizes(False)
        self.Hheader_2.setSortIndicatorShown(False)
        self.Hheader_2.setStretchLastSection(True)
        self.Vheader_2.setVisible(False)
        self.Vheader_2.setCascadingSectionResizes(False)
        self.Vheader_2.setStretchLastSection(False)
        self.table_2.setHorizontalHeaderLabels(self.table_label['products'])
        # Table_3 - requests
        self.table_3 = QTableWidget()
        self.Hheader_3 = self.table_3.horizontalHeader()
        self.Vheader_3 = self.table_3.verticalHeader()
        self.table_3.setAlternatingRowColors(True)
        self.table_3.setColumnCount(6)
        self.Hheader_3.setCascadingSectionResizes(False)
        self.Hheader_3.setSortIndicatorShown(False)
        self.Hheader_3.setStretchLastSection(True)
        self.Vheader_3.setVisible(False)
        self.Vheader_3.setCascadingSectionResizes(False)
        self.Vheader_3.setStretchLastSection(False)
        self.table_3.setHorizontalHeaderLabels(self.table_label['requests'])
        # Actions in toolbar
        self.ac_savetable = QAction(QIcon('Resources/save_as.png'),
                                    'Save Table', self)
        self.ac_addclient = QAction(QIcon('Resources/add-user-male-64.png'),
                                    'Add Client', self)
        self.ac_updateclient = QAction(QIcon('Resources/change-user-64.png'),
                                       'Update Client', self)
        self.ac_deleteclient = QAction(QIcon('Resources/denied-64.png'),
                                       'Delete Client', self)
        self.ac_addproduct = QAction(QIcon('Resources/add_tag.png'),
                                     'Add Product', self)
        self.ac_updateproduct = QAction(QIcon('Resources/update_tag.png'),
                                        'Update Product', self)
        self.ac_deleteproduct = QAction(QIcon('Resources/remove_tag.png'),
                                        'Delete Product', self)
        self.ac_refreshtable = QAction(QIcon('Resources/refresh.png'),
                                       'Refresh Table', self)
        self.ac_aboutapp = QAction(QIcon('Resources/info.png'), 'About App',
                                   self)
        self.ac_developerinfo = QAction(QIcon('Resources/developer_info.png'),
                                        'Developer Info', self)
        self.ac_contactus = QAction(QIcon('Resources/contact_us.png'),
                                    'Contact Us', self)
        # Add Actions to toolbar.
        actions = [
            self.ac_savetable, self.ac_addclient, self.ac_updateclient,
            self.ac_deleteclient, self.ac_addproduct, self.ac_deleteproduct,
            self.ac_updateproduct, self.ac_refreshtable, self.ac_aboutapp,
            self.ac_developerinfo
        ]
        for action in actions:
            self.toolbar.addAction(action)
# Set Widgets
        self.tabwidget.addTab(self.table_1, 'clients')
        self.tabwidget.addTab(self.table_2, 'products')
        self.tabwidget.addTab(self.table_3, 'requests')
        self.addToolBar(self.toolbar)
        self.setCentralWidget(self.tabwidget)
        # Actions Connect
        self.ac_addclient.triggered.connect(self.addClient)
        self.ac_updateclient.triggered.connect(self.updateClient)
        self.ac_deleteclient.triggered.connect(self.deleteClient)
        self.ac_refreshtable.triggered.connect(lambda x: self.refresh(
            self.tabwidget.tabText(self.tabwidget.currentIndex())))
        self.ac_aboutapp.triggered.connect(self.aboutApp)
        self.ac_developerinfo.triggered.connect(self.developerInfo)
        self.loadData(self.exp_Class)
        self.show()

    def Importer_UI(self):
        pass
#LOad Data from Tables Method.

    def loadData(self, usrClass):
        if usrClass == "Exporter":
            db_cur = self.db_conn.cursor()
            db_cur.execute(" SELECT * FROM clients ")
            clients_data = db_cur.fetchall()
            db_cur.execute(" SELECT * FROM products ")
            products_data = db_cur.fetchall()
            db_cur.execute(" SELECT * FROM requests ")
            requests_data = db_cur.fetchall()
            # Get Clients Table
            self.table_1.setRowCount(0)
            for t1_index, t1_row in enumerate(clients_data):
                self.table_1.insertRow(t1_index)
                for t1_feature, t1_value in enumerate(t1_row):
                    self.table_1.setItem(t1_index, t1_feature,
                                         QTableWidgetItem(str(t1_value)))
# Get Products Table
            self.table_2.setRowCount(0)
            for t2_index, t2_row in enumerate(products_data):
                self.table_2.insertRow(t2_index)
                for t2_feature, t2_value in enumerate(t2_row):
                    self.table_2.setItme(t2_index, t2_feature,
                                         QTableWidgetItem(str(t2_value)))
# Get Requests Table
            self.table_3.setRowCount(0)
            for t3_index, t3_row in enumerate(requests_data):
                self.table_3.insertRow(t3_index)
                for t3_feature, t3_value in enumerate(t3_row):
                    self.table_3.setItem(t3_index, t3_feature,
                                         QTableWidgetItem(str(t3_value)))
            db_cur.close()
        elif usrClass == "Importer":
            pass

# Refresh Table method.

    def refresh(self, table):
        db_cur = self.db_conn.cursor()
        sql_query = """ SELECT * FROM {} """.format(table)
        db_cur.execute(sql_query)
        table_data = db_cur.fetchall()
        widget = self.table_1 if table == 'clients' else self.table_2 if table == 'products' else self.table_3
        widget.setRowCount(0)
        for t1_index, t1_row in enumerate(table_data):
            widget.insertRow(t1_index)
            for t1_feature, t1_value in enumerate(t1_row):
                widget.setItem(t1_index, t1_feature,
                               QTableWidgetItem(str(t1_value)))
        db_cur.close()

# Add Client method - connect with Add Client Action

    def addClient(self):
        add_dialog = Add_Client(self.db_conn)
        add_dialog.exec_()

# Update Client method - connect with Add Update Action

    def updateClient(self):
        update_dialog = Update_Client(self.db_conn)
        update_dialog.exec_()

# Delete Client Method - connect with Delete Client Action

    def deleteClient(self):
        delete_dialog = Delete_Client(self.db_conn)
        delete_dialog.exec_()

# Add Product Method - connect with Add Product Action

    def addProduct(self):
        pass

# Update Product Method - connect with Update Product Action

    def aupdateProduct(self):
        pass

# Delete Product Method - connect with Delete Product Action

    def deleteProduct(self):
        pass

# About App method - connect with About App Action

    def aboutApp(self):
        about_app = About_App()
        about_app.exec_()

# Developer Info method - connect with Developer Info Action

    def developerInfo(self):
        developer_info = Developer_Info()
        developer_info.exec_()
예제 #20
0
class EditorMainWindow(QMainWindow):


    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.ui = Ui_ScriptEditor()
        self.ui.setupUi(self)
        #self.ui.actionExit.triggered.connect(self.exit)
        self.splitter = QSplitter(Qt.Vertical, self)
        self.setCentralWidget(self.splitter)
        self.edit_tab = QTabWidget(self.splitter)
        self.console_tab = QTabWidget(self.splitter)
        self.py_console = PythonConsole(self.console_tab)
        self.console_tab.addTab(self.py_console, "&Python console")
        self.js_console = QtQmlConsole(self.console_tab)
        self.console_tab.addTab(self.js_console, "&QtQml console")
        self.editors = []
        self.on_actionNewPython_triggered()

    @pyqtSlot()
    def closeEvent(self, event):
	while(self.editors.__len__()):
	    edit = self.edit_tab.currentWidget()
            if edit:
	        if(edit.isModified()):
		    saveBox = SaveDialog("You have unsaved script. Save it now?")
		    prompt = saveBox.exec_()
		    if(prompt == QMessageBox.Save):
			event.ignore()
		        self.save(True)
		    elif(prompt == QMessageBox.Cancel):
		        event.ignore()
			return
		    elif(prompt == QMessageBox.Discard):
		        event.accept()
                i = self.edit_tab.indexOf(edit)
                self.edit_tab.removeTab(i)
                self.editors.remove(edit)
	event.accept()

	

    @pyqtSlot()
    def on_actionExit_triggered(self):
	while(self.editors.__len__()):
	    edit = self.edit_tab.currentWidget()
            if edit:
	        if(edit.isModified()):
		    saveBox = SaveDialog("You have unsaved script. Save it now?")
		    prompt = saveBox.exec_()
		    if(prompt == QMessageBox.Save):
		        self.save(True)
		    elif(prompt == QMessageBox.Cancel):
		        return
		    elif(prompt == QMessageBox.Discard):
		        pass
		i = self.edit_tab.indexOf(edit)
                self.edit_tab.removeTab(i)
                self.editors.remove(edit)
	self.close()

    @pyqtSlot()
    def on_actionNewPython_triggered(self):
        pyedit = PythonEditorWidget(self.edit_tab)
        pyedit.setPlainText(template_py)
        self.edit_tab.addTab(pyedit, "Python")
        self.edit_tab.setCurrentWidget(pyedit)
        self.editors.append(pyedit)
        self.py_console.attach()
        self.console_tab.setCurrentIndex(0)
        pyedit.setFocus()
        pyedit.view.setFocus()


    @pyqtSlot()
    def on_actionNewQtQml_triggered(self):
        jsedit = QtQmlEditorWidget(self.edit_tab)
        self.edit_tab.addTab(jsedit, "QtQml")
        self.edit_tab.setCurrentWidget(jsedit)
        self.editors.append(jsedit)
        self.js_console.attach()
        self.console_tab.setCurrentIndex(1)


    @pyqtSlot()
    def on_actionClose_triggered(self):
        edit = self.edit_tab.currentWidget()
        if edit:
	    if(edit.isModified()):
		saveBox = SaveDialog("Do you want to save this Script?")
		prompt = saveBox.exec_()
		if(prompt == QMessageBox.Save):
		    self.save(True)
		elif(prompt == QMessageBox.Cancel):
		    return
		elif(prompt == QMessageBox.Discard):
		    pass
            i = self.edit_tab.indexOf(edit)
            self.edit_tab.removeTab(i)
            self.editors.remove(edit)

        
    @pyqtSlot()
    def on_actionClear_triggered(self):
        #edit = self.edit_tab.currentWidget()
	#edit.setPlainText(template_py)
	self.py_console.clear()


    @pyqtSlot()
    def on_actionSave_As_triggered(self):
	self.save()


    @pyqtSlot()
    def on_actionSave_triggered(self):
	self.save(True)


    #Path of the script file in each tab will be stored in tabToolTip
    def save(self, Update = False):
        edit = self.edit_tab.currentWidget()
	contents = str(edit.toPlainText())
	if((Update == False) or (self.edit_tab.tabText(self.edit_tab.currentIndex()) == "Python") ):
	    #Save in its first invocation and Save As will enter  
	    filename = QFileDialog.getSaveFileName(self, "Save File", "", "*.spy")
	    fil = open(filename , 'w')
	    if(filename and self.edit_tab.tabText(self.edit_tab.currentIndex()) == "Python"):
		#Script hasn't been saved before and user specifies a valid filename
	        self.edit_tab.setTabToolTip(self.edit_tab.currentIndex(), filename+'.spy')
	        self.edit_tab.setTabText(self.edit_tab.currentIndex(), os.path.basename(str(filename+'.spy')))
	else:
	    #filename = self.edit_tab.tabText(self.edit_tab.currentIndex())
	    filename = self.edit_tab.tabToolTip(self.edit_tab.currentIndex())
	    fil = open( filename , 'w')
	fil.write(contents)	
	fil.close()
	edit.setModified(False)


    @pyqtSlot()
    def on_actionOpen_triggered(self):
	filename = QFileDialog.getOpenFileName(self,"Open File","","*.spy")
	try:
	    fil = open(filename , 'r')
	except IOError:
	    return
	code = fil.read()
	edit = self.edit_tab.currentWidget()
	self.edit_tab.setTabText(self.edit_tab.currentIndex(), os.path.basename(str(filename)))
	self.edit_tab.setTabToolTip(self.edit_tab.currentIndex(), filename)
	edit.setPlainText(code)
	fil.close()


    @pyqtSlot()
    def on_actionRun_triggered(self):
        self.run()


    @pyqtSlot()
    def on_actionRunConsole_triggered(self):
        self.run(True)


    def run(self, console=False):
        edit = self.edit_tab.currentWidget()
        code = str(edit.toPlainText())
        if isinstance(edit, PythonEditorWidget):
            self.py_console.attach()
            self.console_tab.setCurrentIndex(0)
            if console:
                namespace = self.py_console.namespace
            else:
                namespace = {}
            try:
                exec code in namespace
            except Exception as e:
                traceback.print_exc()
            try:
                Scripter.activeWindow.redraw = True
                Scripter.activeWindow.update()
            except: pass
        else:
            self.js_console.attach()
            self.console_tab.setCurrentIndex(1)
            if console:
                self.js_console.inter.execute(code)
            else:
                self.js_console.inter.execute_code(code)
예제 #21
0
class CodeEditorTabWidget(QWidget):
    """
    Widget which representing code editor with tabs.
    """
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        vertical_layout = QVBoxLayout()
        self.tab_widget = QTabWidget()
        self.tab_widget.setTabBar(TabBar())
        self.tab_widget.setTabsClosable(True)
        self.tab_widget.setUsesScrollButtons(True)
        self.tab_widget.setMovable(True)
        self.tab_widget.tabCloseRequested.connect(self.close_tab)
        self.tab_widget.currentChanged.connect(self.tab_changed)

        self.editor_status_bar = QStatusBar(self)
        self.editor_status_bar.setStyleSheet("QStatusBar{border-bottom: 1px outset grey; border-left: 1px outset grey; border-right: 1px outset grey;}")
        self.editor_status_bar.hide()

        vertical_layout.setSpacing(0)
        vertical_layout.setContentsMargins(5, 22, 0, 0)
        vertical_layout.addWidget(self.tab_widget)
        vertical_layout.addWidget(self.editor_status_bar)

        self.setLayout(vertical_layout)

        self.opened_tabs = 0

    def open_file(self, file_path: str) -> None:
        """
        Open file in new tab.

        Args:
            file_path(str): file path
        """
        with open(file_path, 'r') as f:
            code_editor = CodeEditorWidget(self)
            code_editor.load_file(f)
            code_editor.file_saved = True
            code_editor.opened_file = f.name
            self.add_tab(code_editor, os.path.basename(f.name))

    def new_file(self) -> None:
        """
        Create new tab / file
        """
        code_editor = CodeEditorWidget(self)
        code_editor.file_saved = False
        self.add_tab(code_editor, "NoName")

    def save_file(self, file_path: str = None) -> None:
        """
        Save current file(as).

        Args:
            file_path(str): if file path is not None. Save as method called
        """
        file = file_path or self.get_current_file()
        current_widget = self.get_current_widget()

        with open(file, 'w') as f:
            f.write(current_widget.get_plain_text())

        current_widget.opened_file = file
        current_widget.file_saved = True

        self.tab_changed()
        self.set_tab_text(os.path.basename(file))

    def add_tab(self, code_editor: CodeEditorWidget, file_name: str) -> None:
        """
        Add new tab to the widget.

        Args:
            code_editor(CodeEditorWidget): code editor widget in new tab
            file_name(str): name of new tab - file name
        """
        new_index = self.tab_widget.count()
        self.tab_widget.addTab(code_editor, file_name)
        self.tab_widget.setCurrentIndex(new_index)
        self.opened_tabs += 1

    def tab_changed(self) -> None:
        """
        Change hide/show information in editor status bar.
        Update line and column in main status bar.
        This method is called when currentChanged signal is emitted.
        """
        current_widget = self.get_current_widget()
        if not current_widget:
            self.editor_status_bar.hide()
            return
        else:
            self.editor_status_bar.showMessage(self.get_current_file() or "File not saved")
            self.editor_status_bar.show()

        current_widget.main_window.set_new_cursor_position(current_widget.get_cursor())

    def set_tab_text(self, text: str, index: int = None) -> None:
        """
        Set new text of current tab

        Args:
            text(str): new text
            index(int): index of tab. If None -> use current
        """
        current_index = index or self.tab_widget.currentIndex()
        self.tab_widget.setTabText(current_index, text)

    def close_tab(self, index: int) -> None:
        """
        Close tab at index.

        Args:
            index(int): index of tab
        """
        self.tab_widget.removeTab(index)
        self.opened_tabs -= 1

    def is_file_saved(self) -> bool:
        """
        Return if file in current widget is saved.

        Returns:
            bool: True if file is save else False
        """
        current_tab = self.get_current_widget()
        return current_tab.file_saved

    def get_current_widget(self) -> CodeEditorWidget:
        """
        Return widget in current active tab

        Returns:
            CodeEditorWidget: Code editor in current tab
        """
        return self.tab_widget.currentWidget()

    def get_current_file(self) -> str:
        """
        Return file path of file in current active tab

        Returns:
            str: file path of file in active tab
        """
        return self.get_current_widget().opened_file
예제 #22
0
class TabDocker(QWidget):
    """
    Tab widget for the settingswidgets.

    Inherits:
    QWidget
    """
    sig_start_plot = pyqtSignal()
    latest_active = [None]

    def __init__(self, parent=None, **kwargs):
        """
        Initialise layout for TabDocker

        Arguments:
        parent - Parent widget (default None)

        Return:
        None
        """
        super(TabDocker, self).__init__(parent)
        self.parent = parent
        try:
            self.layout = kwargs['layout']
        except KeyError:
            self.layout = None
        try:
            self.name = kwargs['name']
        except KeyError:
            self.name = None
        self.widgets = []

        layout_tmp = QVBoxLayout(self)
        self.parent_widget = QWidget(self)
        layout_tmp.addWidget(self.parent_widget)
        layout_tmp.setContentsMargins(0, 0, 0, 0)

        layout = QVBoxLayout(self.parent_widget)
        layout.setContentsMargins(0, 0, 0, 0)
        self.tab_widget = QTabWidget(self)
        if self.layout in ('TAB1', 'Settings'):
            tab_bar = MyTabBar(self.tab_widget)
            tab_bar.setObjectName('vertical')
            self.tab_widget.setObjectName('vertical')
            self.tab_widget.setTabBar(tab_bar)
            self.tab_widget.setTabPosition(QTabWidget.West)
        layout.addWidget(self.tab_widget)

        self.tab_widget.currentChanged.connect(self.assign_latest)

    @pyqtSlot(int)
    def assign_latest(self, idx):
        current_name = self.tab_widget.tabText(idx)
        try:
            parent_content = self.parent.content[self.layout].name
        except AttributeError:  # Exception for the Default settings dialog
            parent_content = False
        except TypeError:  # Exception for the Default settings dialog
            parent_content = False
        except KeyError:  # Exception for the main window dialog
            parent_content = False

        check_list = (parent_content, self.name, current_name)

        latest_active = self
        for list_idx, entry in enumerate(check_list):
            if entry == 'Visualisation':
                cur_tab_widget = self.tab_widget.widget(idx)
                try:
                    for i in range(list_idx):
                        idx = cur_tab_widget.currentIndex()
                        cur_tab_widget = cur_tab_widget.widget(idx)
                    latest_active = cur_tab_widget if cur_tab_widget is not None else self
                except:
                    latest_active = self
                break
        if self.latest_active[0] != latest_active:
            self.latest_active[0] = latest_active
            latest_active.sig_start_plot.emit()

    def setCurrentIndex(self, idx):
        """
        Set the current Index of the tab_widget.

        Arguments:
        idx - Index to set

        Returns: Current index of self.tab_widget
        """
        return self.tab_widget.setCurrentIndex(idx)

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

        Arguments:
        idx - Widget to set

        Returns: Current index of self.tab_widget
        """
        return self.tab_widget.setCurrentWidget(widget)

    def currentIndex(self):
        """
        Get the current Index of the tab_widget.

        Returns: Current index of self.tab_widget
        """
        return self.tab_widget.currentIndex()

    def add_tab(self, widget, name, add_widgets=True):
        """
        Add a new tab to the TabDocker

        Arguments:
        widget - Widget to add
        name - Name of the widget

        Return:
        None
        """
        if isinstance(widget, TabDocker):
            widget.parent_widget.setObjectName('tab')
        else:
            pass
        current_state = self.tab_widget.blockSignals(True)
        index = self.tab_widget.addTab(widget, name)
        if add_widgets:
            self.widgets.append(widget)
        self.tab_widget.blockSignals(current_state)
        self.tab_widget.setTabToolTip(index, name)

    def count(self):
        """
        Return the number of tabs.

        Arguments:
        None

        Returns:
        Number of tabs
        """
        return self.tab_widget.count()

    def widget(self, idx):
        """
        Return the widget that belongs to the idx of tabs.

        Arguments:
        idx - Tab index

        Returns:
        Widget
        """
        return self.tab_widget.widget(idx)

    def setMovable(self, status):
        """
        Set the movable status for the tab widgets

        Arguments:
        status - Boolean variable for the status

        Returns:
        None
        """
        return self.tab_widget.setMovable(status)

    def tabText(self, idx):
        """
        Return the text of the tab at idx

        Arguments:
        idx - Index of the tab

        Returns:
        Text of the tab at position isx
        """
        return self.tab_widget.tabText(idx)

    def setTabText(self, idx, text):
        """
        Set the text for the tab at idx

        Arguments:
        idx - Index of the tab
        text - Text of the tab

        Returns:
        None
        """
        return self.tab_widget.setTabText(idx, text)

    def removeTab(self, idx):
        """
        Remove the widget located at tab idx

        Arguments:
        idx - Idx of the widget

        Returns:
        None
        """
        current_state = self.tab_widget.blockSignals(True)
        idx = self.tab_widget.removeTab(idx)
        self.tab_widget.blockSignals(current_state)
        return idx

    def indexOf(self, widget):
        """
        Get the index of the widget.

        Arguments:
        widget - Adress of the widget

        Returns:
        Index of the widget
        """
        return self.tab_widget.indexOf(widget)

    def setTabPosition(self, position):
        """
        Set the tab position of the Tab bar

        Arguments:
        position - Tab position as string ['North', 'East', 'West', 'South']

        Returns:
        None
        """
        tab_position_dict = {
            'North': QTabWidget.North,
            'South': QTabWidget.South,
            'West': QTabWidget.West,
            'East': QTabWidget.East,
        }
        self.tab_widget.setTabPosition(tab_position_dict[position])

    def setTabEnabled(self, index, state):
        """
        Set the tab position index to the enable state.

        Arguments:
        index - Tab position index
        state - State (True or False)

        Returns:
        None
        """
        self.tab_widget.setTabEnabled(index, state)

    def order_tabs(self):
        current_state = self.tab_widget.blockSignals(True)
        widget_tuple = tuple([(self.widget(idx).name, self.widget(idx),
                               self.tab_widget.isTabEnabled(idx))
                              for idx in range(self.count())])
        for idx in reversed(range(self.count())):
            self.removeTab(idx)

        for idx, (name, widget, state) in enumerate(sorted(widget_tuple)):
            self.add_tab(widget, name, add_widgets=False)
            self.setTabEnabled(idx, state)
            if state:
                self.setCurrentIndex(idx)
        self.tab_widget.blockSignals(current_state)

    def enable_tab(self, visible):
        """
        Enable or disable the tab.


        Arguments:
        visible - Enable if True, Disable if False
        name - Name of the tab to disable.

        Returns:
        None
        """
        index = self.parent.content[self.layout].indexOf(self)
        if not visible:
            self.parent.content[self.layout].removeTab(index)
        else:
            self.parent.content[self.layout].add_tab(self, self.name)
            self.parent.content[self.layout].order_tabs()
예제 #23
0
class MainWindow(QDialog, window1.Ui_PyDialog):
    def __init__(self, parent=None):
        global arguments, return_keyword
        self.event_entered = False
        self.event2_entered = False

        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        
        if arguments.dontagain:
            from PyQt5.QtWidgets import QCheckBox
            self.dontagain_checkBox = QCheckBox(_("Don't show or ask this again."), self)
            self.verticalLayout.addWidget(self.dontagain_checkBox)

        if arguments.setdefault:
            from PyQt5.QtWidgets import QCheckBox
            self.dontagain_checkBox = QCheckBox(_("The selected set as default value."), self)
            self.verticalLayout.addWidget(self.dontagain_checkBox)
        
        if arguments.stayontop:
            from PyQt5.QtCore import Qt
            self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.label.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding))

        self.button_ids = ["details_button", "ok_button", "yes_button", "no_button", "continue_button", "save_button", "cancel_button"]
        self.button_names = {
            "details_button":_("Details"), 
            "ok_button":_("Ok"), 
            "yes_button":_("Yes"), 
            "no_button":_("No"), 
            "continue_button":_("Continue"),
            "save_button":_("Save"),
            "cancel_button":_("Cancel")
        }
        
        self.button_values = {}
        self.create_elements()
        self.word_wrap()
        if arguments.showsettings and not arguments.forkedprogressbar:
            self.toolButton.clicked.connect(self.settings_button_clicked)
        else:
            self.toolButton.hide()
            self.spacerItem1.changeSize(0, 0)

    def save_dontask(self, value):
        if arguments.dontagain and dontagain_available() and value != 2:
            if self.dontagain_checkBox.isChecked():
                import configparser
                config = configparser.ConfigParser()
                config[config_section] = {}
                config[config_section][config_key] = value
                with open(config_file, 'w') as file:
                    config.write(file)

    def save_default(self, value):
        if arguments.setdefault and setdefault_setdefault() and value != 2:
            if self.setdefault_checkBox.isChecked():
                import configparser
                config = configparser.ConfigParser()
                config[config_section] = {}
                config[config_section][config_key] = value
                with open(config_file, 'w') as file:
                    config.write(file)

    def word_wrap(self):
        if self.label.sizeHint().width() > 600:
            self.label.setWordWrap(True)
            self.label.setScaledContents(True)
            self.label.setMinimumWidth(600)

    def create_elements(self):
        self.active_buttons = dict((e, False) for e in self.button_names)
        self.progressbar_cancelled = False

        self.hide_unused_elements()
        self.init_conf()
        self.create_buttons()
        self.set_button_labels()

#        noab = len(list(filter(lambda x: self.active_buttons[x], self.active_buttons)))
#        self.reject_value = noab - 1

        
    def hide_unused_elements(self):
        """ Hide the unused elements """
        global arguments
        if not arguments.forkedprogressbar:
            self.progressBar.hide()
        if not arguments.slider:
            self.horizontalSlider.hide()
        if not arguments.combobox:
            self.comboBox.hide()
        if not arguments.inputbox and not arguments.password:
            self.lineEdit.hide()
        if not arguments.combobox and not arguments.password:
            self.label_2.hide()


    def init_conf(self):
        """ Initial configurations (buttons and labels) """
        global arguments
        if arguments.title:
            self.setWindowTitle(pydialog_title)
        if arguments.icon:
            from PyQt5.QtGui import QIcon
            icon = QIcon(arguments.icon)
            self.setWindowIcon(icon)

        if arguments.yesno or arguments.warningyesno:
            self.enable_buttons(["yes_button", "no_button"])
            if arguments.yesno:
                self.label.setText(arguments.yesno)
            else:
                self.label.setText(arguments.warningyesno)

        elif arguments.yesnocancel or arguments.warningyesnocancel:
            self.enable_buttons(["yes_button", "no_button", "cancel_button"])
            if arguments.yesnocancel:
                self.label.setText(arguments.yesnocancel)
            else:
                self.label.setText(arguments.warningyesnocancel)

        elif arguments.sorry or arguments.error or arguments.msgbox or arguments.textbox or arguments.about:
            self.enable_buttons(["ok_button"])
            if arguments.sorry:
                self.label.setText(arguments.sorry)
            elif arguments.error:
                print("itt", arguments.error)
                self.label.setText(arguments.error)
            elif arguments.msgbox:
                self.label.setText(arguments.msgbox)
            elif arguments.textbox:
                from PyQt5.QtWidgets import QTextBrowser
                width = 400
                height = 250
                url = arguments.textbox[0]
                if len(arguments.textbox) > 1:
                    width = int(arguments.textbox[1])
                    if len(arguments.textbox) > 2:
                        height = int(arguments.textbox[2])
                self.textbrowser = QTextBrowser()
                self.textbrowser.setMinimumSize(width, height)
                self.verticalLayout_2.addWidget(self.textbrowser)
                file = open(url, "r")
                self.textbrowser.setText(file.read())
                file.close()
            elif arguments.about:
                self.label.setText("""
                <strong>Pydialog v{}</strong><br><br>
                Authors: <br><center><a href='mailto:[email protected]'>Miklos Horvath</a></center>
                <center><a href='mailto:[email protected]'>Charles Barcza</a></center><br>
                <center><a href='http://blackpantheros.eu'>blackPanther Europe</a></center>""".format(VERSION))

        elif arguments.detailedsorry or arguments.detailederror:
            self.enable_buttons(["details_button", "ok_button"])
            if arguments.detailedsorry:
                self.label.setText(arguments.detailedsorry[0])
                self.details = arguments.detailedsorry[1]
            else:
                self.label.setText(arguments.detailederror[0])
                self.details = arguments.detailederror[1]

        elif arguments.warningcontinuecancel:
            self.enable_buttons(["continue_button", "cancel_button"])
            self.label.setText(arguments.warningcontinuecancel)
        
        elif arguments.forkedprogressbar:
            self.label.setText(arguments.forkedprogressbar[0])
            if len(arguments.forkedprogressbar) > 1:
                self.progressBar.setMaximum(int(arguments.forkedprogressbar[1]))
                
        elif arguments.slider:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.label.setText(arguments.slider[0])
            if len(arguments.slider) > 1:
                self.horizontalSlider.setMinimum(int(arguments.slider[1]))
            if len(arguments.slider) > 2:
                self.horizontalSlider.setMaximum(int(arguments.slider[2]))
            if len(arguments.slider) > 3:
                self.horizontalSlider.setSingleStep(int(arguments.slider[3]))
                self.horizontalSlider.setPageStep(int(arguments.slider[3]))
        
        elif arguments.inputbox:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.label.setText(arguments.inputbox[0])
            if len(arguments.inputbox) > 1:
                self.lineEdit.setText(arguments.inputbox[1])

        elif arguments.password:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.lineEdit.setEchoMode(2)
            self.label.setText(arguments.password[0])
            self.label_2.setText(_("Password:"******"ok_button", "cancel_button"])
            self.label.setText(arguments.combobox[0])
            
        elif arguments.textinputbox:
            from PyQt5.QtWidgets import QTextEdit
            self.enable_buttons(["ok_button"])
            self.textedit = QTextEdit()
            width = 400
            height = 250
            init_text = ""
            self.label.setText(arguments.textinputbox[0])
            if len(arguments.textinputbox) > 1:
                init_text = arguments.textinputbox[1]
                if len(arguments.textinputbox) > 2:
                    width = int(arguments.textinputbox[2])
                    if len(arguments.textinputbox) > 3:
                        height = int(arguments.textinputbox[3])
            self.textedit.setMinimumSize(width, height)
            self.verticalLayout_2.addWidget(self.textedit)
            self.textedit.setText(init_text)            

        elif arguments.checklist or arguments.radiolist or arguments.menu:
            if arguments.checklist:
                scrollLayout, self.checkboxes = self.add_checkboxes()
            else:
                scrollLayout, self.buttonGroup, self.buttongroup_results = self.add_radiobuttons()
            
            #scrollAreaLayout, hscrollbar = self.create_scrollarea(scrollLayout)
            scrollAreaLayout = self.create_scrollarea(scrollLayout)
            
            if arguments.tab:
                from PyQt5.QtWidgets import QTabWidget, QVBoxLayout, QWidget
                
                if arguments.checklist:
                    scrollLayout2, self.checkboxes2 = self.add_checkboxes(True)
                else:
                    scrollLayout2, self.buttonGroup2, self.buttongroup_results2 = self.add_radiobuttons(True)
                        
                #scrollAreaLayout2, hscrollbar2 = self.create_scrollarea(scrollLayout2)                
                scrollAreaLayout2 = self.create_scrollarea(scrollLayout2)                
                
                tab1 = QWidget()
                tab2 = QWidget()
                layout = QVBoxLayout(tab1)
                layout2 = QVBoxLayout(tab2)
                layout.addLayout(scrollAreaLayout)
                layout2.addLayout(scrollAreaLayout2)
                #layout.addWidget(hscrollbar)
                #layout2.addWidget(hscrollbar2)
                self.tabwidget = QTabWidget(self)
                self.tabwidget.addTab(tab1, arguments.tab[0])
                self.tabwidget.addTab(tab2, arguments.tab[1])
                self.verticalLayout_2.addWidget(self.tabwidget)
            else:
                self.verticalLayout_2.addLayout(scrollAreaLayout)
                #self.verticalLayout_2.addWidget(hscrollbar)
            if arguments.checklist:
                self.label.setText(arguments.checklist[0])
            elif arguments.radiolist:
                self.label.setText(arguments.radiolist[0])
            else:
                self.label.setText(arguments.menu[0])
            self.enable_buttons(["ok_button", "cancel_button"])
            
    def create_scrollarea(self, scrollLayout):
            from PyQt5.QtWidgets import QHBoxLayout, QWidget, QScrollArea
            #from PyQt5.QtCore import Qt

            scrollWidget = QWidget()
            scrollAreaLayout = QHBoxLayout()                
            scrollWidget.setLayout(scrollLayout)
            #hscrollbar = QScrollBar()
            #vscrollbar = QScrollBar()
            scrollArea = QScrollArea()
            #scrollArea.setHorizontalScrollBar(hscrollbar)
            #scrollArea.setVerticalScrollBar(vscrollbar)
            #scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            #scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.set_scrollarea_height(scrollArea)
            scrollArea.setWidget(scrollWidget)
            scrollAreaLayout.addWidget(scrollArea)
            #scrollAreaLayout.addWidget(vscrollbar)
            return scrollAreaLayout
            #, hscrollbar
            

    def set_scrollarea_height(self, scrollarea):
        if arguments.checklist:
            elements = (len(arguments.checklist)-1) / 3
        elif arguments.radiolist:
            elements = (len(arguments.radiolist)-1) / 3
        elif arguments.menu:
            elements = (len(arguments.menu)-1) / 2
        if elements < 3:
            pass
        elif elements == 3:
            scrollarea.setMinimumHeight(90)
        elif elements == 4:
            scrollarea.setMinimumHeight(115)
        else:
            scrollarea.setMinimumHeight(140)

    def add_checkboxes(self, tab=False):
        from PyQt5.QtWidgets import QCheckBox, QVBoxLayout
        scrollLayout = QVBoxLayout()
        checkboxes = []
        if tab:
            i = 2
            name = "tab"
        else:
            i = 1
            name = "checklist"
        l = len(arguments.__dict__[name])
        while i < l:
            checkbox = QCheckBox(arguments.__dict__[name][i+1])
            if arguments.__dict__[name][i+2].lower() in ["true", "on"]:
                checkbox.setCheckState(2)
            checkboxes.append({"box":checkbox, "result":arguments.__dict__[name][i]})
            scrollLayout.addWidget(checkbox)
            i += 3
        return scrollLayout, checkboxes
            
    def add_radiobuttons(self, tab=False):
        from PyQt5.QtWidgets import QRadioButton, QButtonGroup, QVBoxLayout
        scrollLayout = QVBoxLayout()
        buttonGroup = QButtonGroup()
        buttongroup_results = {}
        i = 1
        if tab:
            name = "tab"
            i = 2
        elif arguments.radiolist:
            name = "radiolist"
        elif arguments.menu:
            name = "menu"
        arglen = len(arguments.__dict__[name])
        while i < arglen:
            if arguments.radiolist:
                radiobutton = QRadioButton(arguments.__dict__[name][i+1])
                buttongroup_results[radiobutton] = arguments.__dict__[name][i]
                try:
                    if arguments.__dict__[name][i+2].lower() in ["true", "on"]:
                        radiobutton.setChecked(True)
                except:
                    break
                i += 3
            else:
                radiobutton = QRadioButton(arguments.__dict__[name][i+1])
                buttongroup_results[radiobutton] = arguments.__dict__[name][i]
                if i == 1:
                    radiobutton.setChecked(True)
                if arguments.menu and arguments.default:
                    if arguments.__dict__[name][i+1] == arguments.default:
                        radiobutton.setChecked(True)
                i += 2
            scrollLayout.addWidget(radiobutton)
            buttonGroup.addButton(radiobutton)
        return scrollLayout, buttonGroup, buttongroup_results

    def set_button_labels(self):
        """Set the button labels"""
        global arguments
        if arguments.yeslabel and self.active_buttons["yes_button"]:
            self.buttons["yes_button"].setText(arguments.yeslabel)
        if arguments.nolabel and self.active_buttons["no_button"]:
            self.buttons["no_button"].setText(arguments.nolabel)
        if arguments.cancellabel and self.active_buttons["cancel_button"]:
            self.buttons["cancel_button"].setText(arguments.cancellabel)
        if arguments.continuelabel and self.active_buttons["continue_button"]:
            self.buttons["continue_button"].setText(arguments.continuelabel)


    def create_buttons(self):
        global arguments
        self.buttons = {}
        
        i = 0
        for button_id in self.button_ids:
            if self.active_buttons[button_id]:
                self.buttons[button_id] = QPushButton(self.button_names[button_id])
                self.horizontalLayout.addWidget(self.buttons[button_id])
                if button_id == "details_button":
                    self.buttons["details_button"].clicked.connect(self.details_button_clicked)
#                elif button_id == "cancel_button":
#                    self.buttons[button_id].clicked.connect(self.reject)
                else:
                    self.button_values[button_id] = i
                    exec("self.buttons[button_id].clicked.connect(self."+button_id+"_clicked)")
                    i += 1
    
    
    def print_checkboxes(self):
        if arguments.separateoutput:
            fs = '{}'
            data_end = "\n"
        else:
            fs = '"{}"'
            data_end = " "
        for e in self.checkboxes:
            if e["box"].isChecked():
                print(fs.format(e["result"]), end=data_end)
        if arguments.tab:
            for e in self.checkboxes2:
                if e["box"].isChecked():
                    print(fs.format(e["result"]), end=data_end)
                    
    def get_checked_radiobutton(self):
        n = ""
        if arguments.tab:
             if self.tabwidget.currentIndex() == 1:
                 n = "2"
        radiobutton_name = self.__dict__["buttonGroup"+n].checkedButton()
        print(self.__dict__["buttongroup_results"+n][radiobutton_name])

    def get_combo_text(self):
        print(self.comboBox.currentText())

    def ok_button_clicked(self):
        if arguments.slider:
            print(self.horizontalSlider.value())
        elif arguments.inputbox or arguments.password:
            print(self.lineEdit.text())
        elif arguments.checklist:
            self.print_checkboxes()
        elif arguments.radiolist or arguments.menu:
            self.get_checked_radiobutton()
        elif arguments.combobox:
            self.get_combo_text()
        elif arguments.textinputbox:
            print(self.textedit.toPlainText())
        value = str(self.button_values["ok_button"])
        print(return_keyword+str(self.button_values["ok_button"])+">")
        self.save_dontask(value)
        self.done(0)
    
    def yes_button_clicked(self):
        value = str(self.button_values["yes_button"])
        print(return_keyword+value+">")
        self.save_dontask(value)
        self.done(0)
    
    def no_button_clicked(self):
        value = str(self.button_values["no_button"])
        print(return_keyword+value+">")
        self.save_dontask(value)
        self.done(0)
    
    def continue_button_clicked(self):
        value = str(self.button_values["continue_button"])
        print(return_keyword+value+">")
        self.save_dontask(value)
        self.done(0)

    def save_button_clicked(self):
        print(return_keyword+str(self.button_values["save_button"])+">")
        self.done(0)
    
    def cancel_button_clicked(self):
        print(return_keyword+str(self.button_values["cancel_button"])+">")
        self.done(0)
    
    def settings_button_clicked(self):
        print(return_keyword+"100>")
        self.done(0)
    
    def reject(self):
#        value = str(self.reject_value)
#        print(return_keyword+value+">")
        print(return_keyword+">")
        self.done(0)

    def enable_buttons (self, button_list):
        for button in button_list:
            self.active_buttons[button] = True
            
    def details_button_clicked (self):
        self.label.setText(self.label.text() + '\n\n' + self.details)
        self.buttons["details_button"].setDisabled(True)

    def progressbar_cancel_clicked(self):
        self.progressbar_cancelled = True

    def showCancelButton(self):
        if not "cancel_button" in self.buttons:
            self.buttons["cancel_button"] = QPushButton(self.button_names["cancel_button"])
            self.buttons["cancel_button"].clicked.connect(self.progressbar_cancel_clicked)
            self.horizontalLayout.addWidget(self.buttons["cancel_button"])
            self.progressbar_cancelled = False
        self.buttons["cancel_button"].show()
class RobotBeautifyWindow(QWidget):
    def __init__(self):
        super(RobotBeautifyWindow, self).__init__()
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.setObjectName('mainW')
        self.deskTop = QDesktopWidget().availableGeometry()
        self.setFixedSize(self.deskTop.width(), self.deskTop.height())
        self.setWindowIcon(QIcon('./images/logo.png'))
        self.maxWidth = self.deskTop.width()

        # self.warningWindow = QWidget()
        # self.warningWindow.show()
        """init file params"""
        self.openFilePath = ''
        self.saveFilePath = ''
        self.filesDict = {}
        self.editors = {}
        """init some params"""
        self.warningNum = 1

        self.setupUi()

        self.showMaximized()

    def setupUi(self):
        self.createTitle()
        self.createToolsBar()
        # self.createFilesListArea()
        self.createFileDetailArea()
        self.createStatusBar()

        self.titleLabel.doubleClicked.connect(lambda: self.move(0, 0))
        self.closeBtn.clicked.connect(self.close)
        # self.maxBtn.clicked.connect(self.show_start)
        self.minBtn.clicked.connect(self.showMinimized)
        self.newBtn.clicked.connect(self.__addNewTab)
        self.openBtn.clicked.connect(self.__openFile)
        self.saveBtn.clicked.connect(self.__saveFile)
        self.beautifyBtn.clicked.connect(self.__formatContent)
        self.warningBtn.clicked.connect(self.__changeLight)

    def __changeLight(self):
        self.__initLightPos()
        self.lightBtn = [self.redBtn, self.yellowBtn, self.greenBtn]
        if self.warningNum == 0:
            index = 2
        elif self.warningNum <= 10:
            index = 1
        else:
            index = 0
        self.lightBtn[index].move(880 + 55 * index, 10)
        self.lightBtn[index].resize(40, 40)
        self.lightBtn[index].setStyleSheet('border-radius: 20px;')
        if self.warningNum > 10:
            self.warningNum = 0
        else:
            self.warningNum += 5

    def __initLightPos(self):
        for index, btn in enumerate(
            [self.redBtn, self.yellowBtn, self.greenBtn]):
            btn.move(890 + 55 * index, 20)
            btn.resize(20, 20)
            btn.setStyleSheet('border-radius: 10px;')

    def createTitle(self):
        self.titleLabel = MoveLabel(self)
        self.titleLabel.resize(self.maxWidth, 60)
        self.titleLabel.setProperty('class', 'titleLabel')
        self.titleLabel.setText("Robot  Beautify")

        self.logoLabel = QLabel(self)
        self.logoLabel.resize(30, 30)
        self.logoLabel.setObjectName('logoLabel')
        self.logoLabel.move(20, 15)

        self.redBtn = LightBtn('red', self)
        self.redBtn.move(890, 20)
        self.yellowBtn = LightBtn('yellow', self)
        self.yellowBtn.move(945, 20)
        self.greenBtn = LightBtn('green', self)
        self.greenBtn.move(1000, 20)

        # close button
        self.closeBtn = WinBtn(self)
        self.closeBtn.move(self.maxWidth - self.closeBtn.width(), 0)
        self.closeBtn.setIcon(QIcon("./images/close.png"))

        # minimum button
        self.minBtn = WinBtn(self)
        self.minBtn.move(
            self.maxWidth - self.closeBtn.width() - self.minBtn.width(), 0)
        self.minBtn.setIcon(QIcon("./images/min.png"))

    def createToolsBar(self):
        self.toolsBar = QWidget(self)
        self.toolsBar.setFixedSize(60, 970)
        self.toolsBar.move(0, 60)
        self.toolsBar.setObjectName('toolsBarW')

        self.newBtn = ToolBarBtn('+', self.toolsBar)
        self.openBtn = ToolBarBtn('O', self.toolsBar)
        self.saveBtn = ToolBarBtn('S', self.toolsBar)
        self.beautifyBtn = ToolBarBtn('B', self.toolsBar)
        self.warningBtn = ToolBarBtn('W', self.toolsBar)
        self.newBtn.setShortcut('ctrl+n')  # no need space
        self.openBtn.setShortcut('ctrl+o')
        self.saveBtn.setShortcut('ctrl+s')
        self.beautifyBtn.setShortcut('ctrl+b')
        self.warningBtn.setShortcut('ctrl+w')
        self.newBtn.move(10, 10)
        self.openBtn.move(10, 60)
        self.saveBtn.move(10, 110)
        self.beautifyBtn.move(10, 160)
        self.warningBtn.move(10, 210)

    # def createFilesListArea(self):
    #     self.filesListArea = QWidget(self)
    #     self.filesListArea.resize(200, 1020)
    #     self.filesListArea.move(60, 60)
    #     self.filesListArea.setObjectName('filesListArea')

    def createFileDetailArea(self):
        self.fileDetailArea = QWidget(self)
        self.fileDetailArea.resize(1860, 940)
        self.fileDetailArea.move(60, 60)
        self.fileDetailArea.setObjectName('editW')

        self.tabs = QTabWidget(self.fileDetailArea)
        self.tabs.resize(self.tabs.parent().size())
        self.tabs.setTabShape(QTabWidget.Rounded)
        # self.tabs.setDocumentMode(True)
        # self.tabs.setMovable(True)
        self.tabs.setTabsClosable(True)
        self.tabs.setProperty('class', 'tab')

        defaultEditor = QCodeEditor()
        self.editors['untitled'] = [
            defaultEditor,
            RobotHighLighter(defaultEditor.document())
        ]
        self.tabs.addTab(defaultEditor, 'untitled')

        self.tabs.currentChanged.connect(self.__tabChanged)
        self.tabs.tabCloseRequested.connect(self.__tabClosed)

    def createStatusBar(self):
        self.statusBar = QLabel(self)
        self.statusBar.setFixedSize(self.width(), 30)
        self.statusBar.setObjectName('statusBar')
        self.statusBar.move(0, self.height() - self.statusBar.height())

    def __checkContent(self):
        text = self.tabs.currentWidget().toPlainText()
        if not text:
            return None
        self.rc = RobotCheck(
            text
        )  # must exit as an instant property to keep alive after function end
        self.rc.done.connect(self.__checkDone)
        self.rc.start()

    def __checkDone(self, warnings):
        print(warnings)

    def __formatContent(self):
        text = self.tabs.currentWidget().toPlainText()
        if not text:
            return None
        self.fc = RobotFormatter(text)
        self.fc.done.connect(self.__formatDone)
        self.fc.start()

    def __formatDone(self, content):
        self.editors[self.tabs.tabText(
            self.tabs.currentIndex())][0].setPlainText(content)

    def __addNewTab(self):
        if 'untitled' in self.editors.keys():
            self.statusBar.setText(
                'Please save untitled file before create a new one...')
            return None
        defaultEditor = QCodeEditor()
        self.editors['untitled'] = [
            defaultEditor,
            RobotHighLighter(defaultEditor.document())
        ]
        self.tabs.addTab(defaultEditor, 'untitled')
        self.tabs.setCurrentIndex(self.tabs.count() - 1)

    def __tabClosed(self, index):
        count = self.tabs.count()
        key = self.tabs.tabText(index)
        self.tabs.removeTab(index)
        del self.editors[key]

        if count == 1:
            self.__addNewTab()

    def __tabChanged(self, index):
        self.statusBar.setText(self.filesDict.get(self.tabs.tabText(index),
                                                  ''))

    def __openFile(self):
        if not self.openFilePath:
            file = QFileDialog().getOpenFileName(parent=self,
                                                 caption='Select File',
                                                 directory=os.path.join(
                                                     os.path.expanduser("~"),
                                                     'Desktop'),
                                                 filter='Robot Files(*.robot)')
        else:
            file = QFileDialog().getOpenFileName(self,
                                                 caption='Select File',
                                                 directory=self.openFilePath,
                                                 filter='Robot Files(*.robot)')
        if file[0]:
            self.openFilePath = os.path.dirname(file[0])
            tmp = self.tabs.tabText(self.tabs.currentIndex())
            key = file[0].split('/')[-1]
            self.filesDict[key] = file[0]
            if not tmp.endswith('.robot'):  # untitled
                self.editors[key] = self.editors.get(tmp)
                del self.editors[tmp]
                self.tabs.setTabText(self.tabs.currentIndex(), key)
            else:
                editor = QCodeEditor()
                self.editors[key] = [
                    editor, RobotHighLighter(editor.document())
                ]
                self.tabs.insertTab(self.tabs.count(), editor, key)
                self.tabs.setCurrentIndex(self.tabs.count() - 1)
            self.__tabChanged(self.tabs.currentIndex())
            with open(file[0], 'r') as f:
                for line in f.readlines():
                    self.editors.get(key)[0].appendPlainText(line.strip('\n'))

    def __saveFile(self):
        key = self.tabs.tabText(self.tabs.currentIndex())
        if key == 'untitled':
            if not self.saveFilePath:
                file = QFileDialog().getSaveFileName(
                    parent=self,
                    caption='Save File',
                    directory=os.path.join(os.path.expanduser("~"),
                                           'untitled'),
                    filter='Robot Files(*.robot)')
            else:
                file = QFileDialog().getSaveFileName(
                    self,
                    caption='Save File',
                    directory=self.saveFilePath,
                    filter='Robot Files(*.robot)')
            if file[0]:
                self.saveFilePath = os.path.dirname(file[0])
                print('saveFilePath:', self.saveFilePath)
                fileName = file[0]
                key = file[0].split('/')[-1]
                self.filesDict[key] = file[0]
                self.editors[key] = self.editors.get('untitled')
                del self.editors['untitled']
                self.tabs.setTabText(self.tabs.currentIndex(), key)
                self.__tabChanged(self.tabs.currentIndex())
            else:
                fileName = ''
        else:
            fileName = self.filesDict.get(key)
        if fileName:
            with open(fileName, 'w') as f:
                text = self.tabs.currentWidget().toPlainText()
                print(text)
                f.write(text)
            self.__checkContent()
class ImageTransformCtrlWidget(_AbstractCtrlWidget):
    """Control widget for image transform in the ImageTool."""

    extract_concentric_rings_sgn = pyqtSignal()

    transform_type_changed_sgn = pyqtSignal(int)

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

        self._ma_window_le = SmartLineEdit("1")
        validator = QIntValidator()
        validator.setBottom(1)
        self._ma_window_le.setValidator(validator)

        self._concentric_rings = _ConcentricRingsCtrlWidget()
        self._fourier_transform = _FourierTransformCtrlWidget()
        self._edge_detection = _EdgeDetectionCtrlWidget()

        self._opt_tab = QTabWidget()
        self._opt_tab.addTab(self._concentric_rings, "Concentric rings")
        self._opt_tab.addTab(self._fourier_transform, "Fourier transform")
        self._opt_tab.addTab(self._edge_detection, "Edge detection")

        self._non_reconfigurable_widgets = [
            self._concentric_rings.detect_btn,
        ]

        self.initUI()
        self.initConnections()

    def initUI(self):
        """Override."""
        common = QFrame()
        common_layout = QGridLayout()
        common_layout.addWidget(QLabel("Moving average window: "), 0, 0)
        common_layout.addWidget(self._ma_window_le, 0, 1)
        common.setLayout(common_layout)

        layout = QHBoxLayout()
        layout.addWidget(common)
        layout.addWidget(self._opt_tab)
        self.setLayout(layout)

        self.setFixedHeight(self.minimumSizeHint().height())

    def initConnections(self):
        """Override."""
        mediator = self._mediator

        self._ma_window_le.value_changed_sgn.connect(
            mediator.onItMaWindowChange)

        self._opt_tab.currentChanged.connect(mediator.onItTransformTypeChange)
        self._opt_tab.currentChanged.connect(self.transform_type_changed_sgn)

        cr = self._concentric_rings
        cr.detect_btn.clicked.connect(self.extract_concentric_rings_sgn)
        cr.cx_le.value_changed_sgn.connect(mediator.onItCrCxChange)
        cr.cy_le.value_changed_sgn.connect(mediator.onItCrCyChange)
        cr.prominence_le.value_changed_sgn.connect(
            mediator.onItCrProminenceChange)
        cr.distance_le.value_changed_sgn.connect(mediator.onItCrDistanceChange)
        cr.min_count_le.value_changed_sgn.connect(
            mediator.onItCrMinCountChange)

        fft = self._fourier_transform
        fft.logrithmic_cb.toggled.connect(
            mediator.onItFftLogrithmicScaleChange)

        ed = self._edge_detection
        ed.kernel_size_sp.valueChanged.connect(mediator.onItEdKernelSizeChange)
        ed.sigma_sp.valueChanged.connect(mediator.onItEdSigmaChange)
        ed.threshold_le.value_changed_sgn.connect(
            mediator.onItEdThresholdChange)

    def updateMetaData(self):
        """Override."""
        self._ma_window_le.returnPressed.emit()

        if self.isVisible():
            self.registerTransformType()
        else:
            self.unregisterTransformType()

        cr = self._concentric_rings
        cr.cx_le.returnPressed.emit()
        cr.cy_le.returnPressed.emit()
        cr.prominence_le.returnPressed.emit()
        cr.distance_le.returnPressed.emit()
        cr.min_count_le.returnPressed.emit()

        fft = self._fourier_transform
        fft.logrithmic_cb.toggled.emit(fft.logrithmic_cb.isChecked())

        ed = self._edge_detection
        ed.kernel_size_sp.valueChanged.emit(ed.kernel_size_sp.value())
        ed.sigma_sp.valueChanged.emit(ed.sigma_sp.value())
        ed.threshold_le.returnPressed.emit()

        return True

    def loadMetaData(self):
        """Override."""
        cfg = self._meta.hget_all(mt.IMAGE_TRANSFORM_PROC)

        self._updateWidgetValue(self._ma_window_le, cfg, "ma_window")

        # do not load transform type since it is not an "input"

        cr = self._concentric_rings
        self._updateWidgetValue(cr.cx_le, cfg, "cr:cx")
        self._updateWidgetValue(cr.cy_le, cfg, "cr:cy")
        self._updateWidgetValue(cr.prominence_le, cfg, "cr:prominence")
        self._updateWidgetValue(cr.distance_le, cfg, "cr:distance")
        self._updateWidgetValue(cr.min_count_le, cfg, "cr:min_count")

        fft = self._fourier_transform
        self._updateWidgetValue(fft.logrithmic_cb, cfg, "fft:logrithmic")

        ed = self._edge_detection
        self._updateWidgetValue(ed.kernel_size_sp,
                                cfg,
                                "ed:kernel_size",
                                cast=int)
        self._updateWidgetValue(ed.sigma_sp, cfg, "ed:sigma", cast=float)
        self._updateWidgetValue(ed.threshold_le, cfg, "ed:threshold")

    def registerTransformType(self):
        self._opt_tab.currentChanged.emit(self._opt_tab.currentIndex())

    def unregisterTransformType(self):
        self._mediator.onItTransformTypeChange(
            int(ImageTransformType.UNDEFINED))

    def extractFeature(self, img):
        return self._opt_tab.currentWidget().extractFeature(img)
예제 #26
0
class Calculatormainwindow(QWidget):
    """
        计算器主界面窗口
    """
    _startPos = None
    _endPos = None
    _isTracking = None

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

        self.init()
        self.setup_ui()
        self.load_qss()

    def init(self):
        self.setWindowFlags(Qt.FramelessWindowHint)  # 设置无边框
        self.setAttribute(Qt.WA_TranslucentBackground, True)  # 将form设置为透明
        self.setMinimumHeight(Const.MINIMUMHEIGHT)  # 设置窗体最小高度
        self.setMinimumWidth(Const.MINIMUMWIDTH)  # 设置窗体最小宽度

        self.setWindowTitle('计算器')
        self.setWindowIcon(QIcon("./image/calculator.jpg"))

    def setup_ui(self):
        # 布局
        all_layout = QVBoxLayout()
        all_layout.setObjectName('all_layout')
        all_layout.setSpacing(Const.SET_SPACING)
        self.setLayout(all_layout)

        # 调整布局与边界距离
        all_layout.setContentsMargins(Const.SET_CONTENTSMARGINS,
                                      Const.SET_CONTENTSMARGINS,
                                      Const.SET_CONTENTSMARGINS,
                                      Const.SET_CONTENTSMARGINS)

        # 调用自定义标题栏
        self.title = CommonhelperTitleBar()
        self.title.setObjectName('title')

        self.title.spinnerBtn = QPushButton(self.title)  # 创建下拉列表按钮
        self.title.spinnerBtn.setObjectName("spinnerBtn")
        self.title.spinnerBtn.resize(40, 40)
        self.title.spinnerBtn.setIconSize(QSize(30, 30))
        self.title.spinnerBtn.setIcon(QIcon(Const.SPINNERBTN_ICON))
        self.title.spinnerBtn.move(60, 0)
        self.title.spinnerBtn.setCursor(QCursor(Qt.PointingHandCursor))
        self.title.spinnerBtn.setToolTip("功能列表")
        self.title.spinnerBtn.clicked.connect(self.spinner_btn_pressed)

        # 自定义最小化、关闭按钮槽函数连接
        self.title.minButton.clicked.connect(self.show_mininized_window)
        self.title.closeButton.clicked.connect(self.close_window)

        # 隐藏复原和最大化按钮(不可用)
        self.title.restoreButton.setHidden(True)
        self.title.maxButton.setHidden(True)

        # 自定义标题Icon和内容
        title_icon = QPixmap("./image/calculator.jpg")
        self.title.iconLabel.setPixmap(title_icon.scaled(40, 40))
        self.title.titleLabel.setText('标准计算器')
        self.title.titleLabel.setFont(QFont("STSong", 16))  # 华文宋体
        self.title.titleLabel.resize(40, 40)

        # 界面主窗口
        self.centerWidget = QTabWidget()
        self.centerWidget.setObjectName('centerWidget')

        all_layout.addWidget(self.title)
        all_layout.addWidget(self.centerWidget)

        # 下拉列表
        self.spinner()
        # 加载窗口
        self.show_win()

    # ************************** 业务逻辑 *************************
    def load_qss(self):
        """
        加载样式表
        :return:
        """
        style_file = './Window/childWindow/calculatorWindow/Qss/CalculatorMainWindow.qss'
        qss_style = CommonhelperQss.read_qss(style_file)
        self.setStyleSheet(qss_style)

    def show_win(self):
        """
        显示默认窗口你(高级计算器窗口)
        :return:
        """
        self.standardCalculator = Standardcalculator()
        self.scienceCalculator = Sciencecalculator()
        self.baseConversionWindow = Uiconversionofnumbersystems()
        self.centerWidget.addTab(self.standardCalculator, "标准计算器")
        self.centerWidget.addTab(self.scienceCalculator, "科学计算器")
        self.centerWidget.addTab(self.baseConversionWindow, "程序员计算器")

    def paintEvent(self, event):
        """
        重写paintEvent,实现边框阴影
        :param event:
        :return:
        """
        path = QPainterPath()
        path.setFillRule(Qt.WindingFill)
        path.addRect(10, 10, self.width() - 20, self.height() - 20)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.fillPath(path, QBrush(Qt.white))
        color = QColor(0, 0, 0, 50)
        for i in range(0, 10):
            path = QPainterPath()
            path.setFillRule(Qt.WindingFill)
            path.addRect(10 - i, 10 - i,
                         self.width() - (10 - i) * 2,
                         self.height() - (10 - i) * 2)
            color.setAlpha(150 - math.sqrt(i) * 50)
            painter.setPen(color)
            painter.drawPath(path)

    # #########################自定义下拉列表 #######################开始
    # 自定义下拉列表,实现几种计算界面之间的切换
    def spinner(self):
        """
        表自定义下拉列表
        :return:
        """
        # 创建下拉列表框
        self.spinnerQwidget = QWidget(self)
        self.spinnerQwidget.setObjectName('spinnerQwidget')
        self.spinnerQwidget.setGeometry(70, 50, 250, 250)
        self.spinnerQwidget.setStyleSheet('background-color:white;')
        self.spinnerQwidget.hide()

        self.spinnerLayout = QVBoxLayout(self.spinnerQwidget)
        self.spinnerLayout.setObjectName("spinnerLayout")

        # 标准计算器切换按钮
        self.StandardCalculatorBtn = QPushButton("标准计算器")
        self.StandardCalculatorBtn.setObjectName("calculatorBtn")
        self.StandardCalculatorBtn.clicked.connect(
            lambda: self.calculator_win_change(1))
        # 科学计算器切换按钮
        self.scienceCalculatorBtn = QPushButton("科学计算器")
        self.scienceCalculatorBtn.setObjectName("scienceCalculatorBtn")
        self.scienceCalculatorBtn.clicked.connect(
            lambda: self.calculator_win_change(2))
        # 程序员计算器切换按钮
        self.baseConversionBtn = QPushButton("程序员计算器")
        self.baseConversionBtn.setObjectName("baseConversionBtn")
        self.baseConversionBtn.clicked.connect(
            lambda: self.calculator_win_change(3))

        self.StandardCalculatorBtn.setStyleSheet("background-color:gray;")
        self.baseConversionBtn.setStyleSheet("background-color:gray;")
        self.spinnerQuitBtn = QPushButton(self.spinnerQwidget)
        self.spinnerQuitBtn.setObjectName("spinnerQuitBtn")
        self.spinnerQuitBtn.setIcon(QIcon("./image/spinnerQuit.png"))
        self.spinnerQuitBtn.setStyleSheet("background-color:cyan;")
        self.spinnerQuitBtn.clicked.connect(lambda: self.spinner_btn_pressed())

        # 分隔控件的空白窗口
        self.separator = QWidget(self.spinnerQwidget)
        self.separator.setObjectName("separator")
        self.separator.resize(150, 20)

        # 往下拉列表框添加控件
        self.spinnerLayout.addWidget(self.StandardCalculatorBtn)
        self.spinnerLayout.addWidget(self.scienceCalculatorBtn)
        self.spinnerLayout.addWidget(self.baseConversionBtn)
        self.spinnerLayout.addWidget(self.separator)
        self.spinnerLayout.addWidget(self.spinnerQuitBtn)

    # #########################自定义下拉列表 #######################结束

    # ***************************** 业务逻辑 ********************************

    # ####################设置窗口大小槽函数####################开始
    def show_mininized_window(self):
        """
        最小化窗口
        :return:
        """
        self.showMinimized()

    # # 最大化窗口
    # def show_maximized_window(self):
    #     '''
    #
    #     :return:
    #     '''
    #     self.showMaximized()

    # # 复原窗口
    # def show_restore_window(self):
    #     '''
    #
    #     :return:
    #     '''
    #     if self.isMaximized():
    #         self.showNormal()
    #     else:
    #         self.showMaximized()

    def close_window(self):
        """
        关闭窗口
        :return:
        """
        self.close()

    def set_title(self, _str):
        """
        设置状态信息
        :param _str:
        :return:
        """
        self.titleLabel.set_text(_str)

    def set_icon(self, pix):
        """
        设置icon
        :param pix:
        :return:
        """
        self.iconLabel.setPixmap(
            pix.scaled(self.iconLabel.size() -
                       QSize(Const.TITLE_ICON_MAG, Const.TITLE_ICON_MAG)))

    # ####################设置窗口大小槽函数####################结束

    # #########################calculator窗口切换#######################开始

    def calculator_win_change(self, flag):
        """
        窗口切换
        :param flag:
        :return:
        """
        self.flag = flag
        if self.flag == 1:
            if self.centerWidget.currentIndex() == self.flag - 1:
                QMessageBox.information(self.centerWidget, "提示", "已经为当前窗口!",
                                        QMessageBox.Ok)
            else:
                self.centerWidget.setCurrentIndex(self.flag - 1)
                self.title.titleLabel.setText('标准计算器')
        elif self.flag == 2:
            if self.centerWidget.currentIndex() == self.flag - 1:
                QMessageBox.information(self.centerWidget, "提示", "已经为当前窗口!",
                                        QMessageBox.Ok)
            else:
                self.centerWidget.setCurrentIndex(self.flag - 1)
                self.title.titleLabel.setText('科学计算器')
        elif self.flag == 3:
            if self.centerWidget.currentIndex() == self.flag - 1:
                QMessageBox.information(self.centerWidget, "提示", "已经为当前窗口!",
                                        QMessageBox.Ok)
            else:
                self.centerWidget.setCurrentIndex(self.flag - 1)
                self.title.titleLabel.setText('程序员计算器')

    # #########################calculator窗口切换#######################结束

    # #########################实现窗口拖动#######################开始
    # 重写鼠标事件
    def mousePressEvent(self, e: QMouseEvent):
        """
        鼠标点击事件
        :param e:
        :return:
        """
        if e.button() == Qt.LeftButton:
            self._isTracking = True
            self._starPos = QPoint(e.x(), e.y())

    def mouseMoveEvent(self, e: QMouseEvent):
        """
        鼠标移动事件
        :param e:
        :return:
        """
        self._endPos = e.pos() - self._starPos
        self.move(self.pos() + self._endPos)

    def mouseReleaseEvent(self, e: QMouseEvent):
        """
        鼠标释放事件
        :param e:
        :return:
        """
        if e.button() == Qt.LeftButton:
            self._isTracking = False
            self._starPos = None
            self._endPos = None

    # #########################实现窗口拖动#######################结束

    def spinner_btn_pressed(self):
        """
        下拉列表槽函数
        :return:
        """
        if self.spinnerQwidget.isHidden():
            self.spinnerQwidget.show()
        else:
            self.spinnerQwidget.hide()

    def spinner_quit_btn_pressed(self):
        """
        隐藏下拉列表按钮槽函数
        :return:
        """
        self.spinnerQwidget.hide()
예제 #27
0
class MainWindows(QWidget):
    ## Main class 4 tabs :  cameras
    def __init__(self):
        super().__init__()

        self.left = 100
        self.top = 30
        self.width = 1400
        self.height = 1700
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setWindowTitle('Lolita Cameras')
        self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
        p = pathlib.Path(__file__)
        sepa = os.sep
        self.icon = str(p.parent) + sepa + 'icons' + sepa
        self.setWindowIcon(QIcon(self.icon + 'LOA.png'))

        self.setup()
        self.actionButton()

    def setup(self):

        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.setContentsMargins(1, 1, 1, 1)
        self.tabs = QTabWidget()
        self.tabs.setContentsMargins(1, 1, 1, 1)
        pathVisu = 'C:/Users/loa/Desktop/Python/camera/confCamera.ini'
        self.tab0 = CameraMotorLoop.CAMERAMOTOR(cam="cam2",
                                                fft='off',
                                                meas='on',
                                                affLight=False,
                                                aff='left',
                                                separate=False,
                                                multi=False,
                                                confpath=pathVisu,
                                                loop=True)
        self.tab1 = camera2.CAMERA(cam="cam3",
                                   fft='off',
                                   meas='on',
                                   affLight=False,
                                   aff='left',
                                   separate=False,
                                   multi=False,
                                   confpath=pathVisu)
        self.tab2 = camera2.CAMERA(cam="cam1",
                                   fft='off',
                                   meas='on',
                                   affLight=False,
                                   aff='left',
                                   separate=False,
                                   multi=False,
                                   confpath=pathVisu)
        self.tab3 = camera2.CAMERA(cam='cam4',
                                   fft='off',
                                   meas='on',
                                   affLight=False,
                                   aff='left',
                                   separate=False,
                                   multi=False,
                                   confpath=pathVisu)
        self.tab4 = CameraMotorLoop.CAMERAMOTOR(cam='cam5',
                                                fft='off',
                                                meas='on',
                                                affLight=False,
                                                aff='left',
                                                separate=False,
                                                multi=False,
                                                confpath=pathVisu,
                                                loop=True)
        #        self.tab2=App4Cam()

        self.tabs.addTab(self.tab0, self.tab0.ccdName)
        self.tabs.addTab(self.tab1, self.tab1.ccdName)
        self.tabs.addTab(self.tab2, self.tab2.ccdName)
        self.tabs.addTab(self.tab3, self.tab3.ccdName)
        self.tabs.addTab(self.tab4, self.tab4.ccdName)
        #self.tabs.addTab(self.tab2,'    P3    ')

        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    def changeTab(self):
        print('tab change', 'tab is', self.tabs.currentIndex())
        # self.tab=[self.tab0,self.tab1]
        # self.tab0.stopRun()
        # self.tab1.stopRun()
        #self.tab2.stopRun()

    def actionButton(self):
        self.tabs.currentChanged.connect(self.changeTab)

    def closeEvent(self, event):
        # exit
        event.accept()
예제 #28
0
class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.comics_tabs = {}
        self.comics_tabs_index = {}
        self.comics_pictures = {}
        self.comics_current_page = {}
        self.comics_picture_label = {}
        self.setGeometry(50, 50, 850, 600)
        self.setWindowTitle('Comics')
        self.init_GUI()

    def init_GUI(self):
        # create toolbar
        self.toolbar = QToolBar('Fonctionnalités')
        self.addToolBar(self.toolbar)
        self.toolbar.setIconSize(QSize(32, 32))

        # add "add a comic" button to toolbar
        self.add_action = QAction(
            QIcon('icons/add.png'), 'Nouvelle bande déssinée', self)
        self.add_action.setStatusTip('Ajouter une nouvelle bande déssinée')
        self.add_action.triggered.connect(add_comic)
        self.add_action.setShortcut(QKeySequence('Ctrl+N'))
        self.toolbar.addAction(self.add_action)

        # add "previous" button to toolbar
        self.previous_action = QAction(
            QIcon('icons/previous.png'), 'Page précédente', self)
        self.previous_action.setStatusTip('Passer à la page précédente')
        self.previous_action.triggered.connect(self.previous_page)
        self.previous_action.setShortcut(QKeySequence('Ctrl+L'))
        self.toolbar.addAction(self.previous_action)

        # add "next" button to toolbar
        self.next_action = QAction(
            QIcon('icons/next.png'), 'Page suivante', self)
        self.next_action.setStatusTip('Passer à la page suivante')
        self.next_action.triggered.connect(self.next_page)
        self.next_action.setShortcut(QKeySequence('Ctrl+O'))
        self.toolbar.addAction(self.next_action)

        # add main view
        self.centralwidget = QWidget(self)
        self.centralwidget.setObjectName('centralwidget')
        self.setCentralWidget(self.centralwidget)

        # add tabs widget
        self.tab_widget = QTabWidget(self.centralwidget)
        self.tab_widget.setGeometry(QRect(0, 0, 850, 600))
        self.tab_widget.setObjectName('tab_widget')
        self.tab_widget.setTabsClosable(False)
        self.tab_widget.tabCloseRequested.connect(lambda index: self.remove_tab(index))

        # add library tab
        self.library_tab = QWidget()
        self.library_tab.setObjectName('library_tab')
        self.tab_widget.addTab(self.library_tab, 'Bibliothèque')

        # show library in library tab
        self.scroll_area = QScrollArea(self.library_tab)
        self.scroll_area.setGeometry(QRect(0, 0, 850, 600))
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setObjectName('scroll_area')
        self.scroll_area_widget_contents = QWidget()
        self.scroll_area_widget_contents.setGeometry(QRect(0, 0, 850, 600))
        self.scroll_area_widget_contents.setObjectName(
            'scroll_area_widget_contents')
        self.scroll_area.setWidget(self.scroll_area_widget_contents)
        self.table_widget = QTableWidget(self.scroll_area_widget_contents)
        self.table_widget.setGeometry(QRect(0, 0, 850, 600))
        self.table_widget.setRowCount(1)
        self.table_widget.setColumnCount(8)
        self.table_widget.setObjectName('table_widget')
        self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.set_library()

    ### actions ###
    def previous_page(self):
        if not self.tab_widget.currentIndex() == 0:
            current_comics = None
            for key, value in self.comics_tabs.items():
                if value == self.tab_widget.currentWidget():
                    current_comics = key
            if self.comics_current_page[current_comics] >= 1:
                self.comics_current_page[current_comics] -= 1
                page = self.comics_current_page[current_comics]
                self.comics_picture_label[current_comics].setPixmap(QPixmap(
                    'library/' + current_comics + '/' + self.comics_pictures[current_comics][page]))

    def next_page(self):
        if not self.tab_widget.currentIndex() == 0:
            current_comics = None
            for key, value in self.comics_tabs.items():
                if value == self.tab_widget.currentWidget():
                    current_comics = key
            if self.comics_current_page[current_comics] < len(self.comics_pictures[current_comics]) - 1:
                self.comics_current_page[current_comics] += 1
                page = self.comics_current_page[current_comics]
                self.comics_picture_label[current_comics].setPixmap(QPixmap(
                    'library/' + current_comics + '/' + self.comics_pictures[current_comics][page]))

    def make_read_comic(self, comic):
        def read_comic():
            comics_title = os.path.splitext(comic)[0]
            if not comics_title in self.comics_tabs_index:
                self.comics_tabs[comics_title] = QWidget()
                self.comics_tabs[comics_title].setObjectName('comic_view_tab')
                self.tab_widget.addTab(
                    self.comics_tabs[comics_title], comics_title)
                self.comics_tabs_index[comics_title] = self.tab_widget.indexOf(self.comics_tabs[comics_title])

                self.comics_picture_label[comics_title] = QLabel(
                    self.comics_tabs[comics_title])
                self.comics_picture_label[comics_title].setGeometry(
                    QRect(0, 0, 350, 500))
                self.comics_picture_label[comics_title].setScaledContents(True)
                self.comics_picture_label[comics_title].setAlignment(Qt.AlignCenter)
                self.comics_picture_label[comics_title].setObjectName(comics_title)

                comicParser = COMICParser('library/' + comic)
                self.comics_pictures[comics_title] = comicParser.read_book()
                self.comics_current_page[comics_title] = 0

                self.comics_picture_label[comics_title].setPixmap(QPixmap(
                    'library/' + comics_title + '/' + self.comics_pictures[comics_title][0]))
                close_button = QPushButton('Fermer la BD', self.comics_tabs[comics_title])
                close_button.setGeometry(250, 510, 100, 25)
                def close():
                    self.remove_tab(self.tab_widget.indexOf(self.comics_tabs[comics_title]))
                close_button.clicked.connect(close)
        return read_comic

    def remove_tab(self, index, tab_type = ''):
        if index > 0 and tab_type == 'edit':
            self.tab_widget.removeTab(index)
            self.comics_tabs_index = {}
            for key, value in self.comics_tabs.items():
                self.comics_tabs_index[key] = self.tab_widget.indexOf(value)
        elif index > 0:
            self.tab_widget.removeTab(index)
            comics_to_close = None
            for key, value in self.comics_tabs_index.items():
                if value == index:
                    comics_to_close = key
            del self.comics_tabs[comics_to_close]
            del self.comics_current_page[comics_to_close]
            del self.comics_picture_label[comics_to_close]
            del self.comics_pictures[comics_to_close]
            self.comics_tabs_index = {}
            for key, value in self.comics_tabs.items():
                self.comics_tabs_index[key] = self.tab_widget.indexOf(value)

    def make_open_edit_tab(self, file):
        def open_edit_tab():
            comicParser = COMICParser('library/' + file)
            file_infos = comicParser.getMetadata(os.path.splitext(file)[0])
            edit_tab = QWidget()
            edit_tab.setObjectName('edit_tab')
            self.tab_widget.addTab(edit_tab, 'Modifier ' + file)
            QLabel('Auteur :', edit_tab).setGeometry(0, 0, 400, 20)
            author_text = QLineEdit('<unknown>', edit_tab)
            if 'author' in file_infos:
                author_text.setText(file_infos['author'])
            author_text.setGeometry(0, 20, 400, 20)
            author_text.setObjectName('author_text')
            QLabel('Tags :', edit_tab).setGeometry(0, 50, 400, 20)
            tags_text = QLineEdit('tag1, tag2...', edit_tab)
            if 'tags' in file_infos:
                tags_text.setText(file_infos['tags'])
            tags_text.setGeometry(0, 70, 400, 20)
            tags_text.setObjectName('tags_text')
            QLabel('Quality :', edit_tab).setGeometry(0, 100, 400, 20)
            quality_text = QLineEdit('-/10', edit_tab)
            if 'quality' in file_infos:
                quality_text.setText(file_infos['quality'])
            quality_text.setGeometry(0, 120, 400, 20)
            quality_text.setObjectName('quality_text')
            cancel_button = QPushButton('Annuler', edit_tab)
            cancel_button.setGeometry(190, 150, 100, 25)
            validate_button = QPushButton('Enregistrer', edit_tab)
            validate_button.setGeometry(300, 150, 100, 25)
            def cancel():
                self.remove_tab(self.tab_widget.indexOf(edit_tab), 'edit')
            def edit_info():
                comicParser.generate_metadata(os.path.splitext(file)[0], author_text.text(), tags_text.text(), quality_text.text())
                self.remove_tab(self.tab_widget.indexOf(edit_tab), 'edit')
                self.set_library()
            cancel_button.clicked.connect(cancel)
            validate_button.clicked.connect(edit_info)
        return open_edit_tab

    def set_library(self):
        self.table_widget.clear()
        self.table_widget.setRowCount(1)
        self.table_widget.setItem(0, 0, QTableWidgetItem())
        self.table_widget.item(0, 0).setText('Cover')
        self.table_widget.setItem(0, 1, QTableWidgetItem())
        self.table_widget.item(0, 1).setText('Titre')
        self.table_widget.setItem(0, 2, QTableWidgetItem())
        self.table_widget.item(0, 2).setText('Auteur')
        self.table_widget.setItem(0, 3, QTableWidgetItem())
        self.table_widget.item(0, 3).setText('Année')
        self.table_widget.setItem(0, 4, QTableWidgetItem())
        self.table_widget.item(0, 4).setText('Tags')
        self.table_widget.setItem(0, 5, QTableWidgetItem())
        self.table_widget.item(0, 5).setText('Quality')

        self.library_files = get_library_files()
        index = 0
        for comic in self.library_files:
            if os.path.splitext(comic)[1].lower() == '.cbz':
                unzip('library/' + comic, 'library/' + os.path.splitext(comic)[0])
            else:
                unrar('library/' + comic, 'library/' + os.path.splitext(comic)[0])
            index += 1
            self.table_widget.insertRow(index)
            cover_widget = QWidget()
            self.table_widget.setCellWidget(index, 0, cover_widget)
            self.table_widget.setRowHeight(index, 150)
            comicParser = COMICParser('library/' + comic)
            pictures = comicParser.read_book()
            cover_label = QLabel(cover_widget)
            cover_label.setGeometry(
                    QRect(0, 0, 100, 150))
            cover_label.setScaledContents(True)
            cover_label.setAlignment(Qt.AlignCenter)
            cover_label.setObjectName(comic)
            cover_label.setPixmap(QPixmap('library/' + os.path.splitext(comic)[0] + '/' + pictures[0]))
            self.table_widget.setItem(index, 1, QTableWidgetItem())
            self.table_widget.item(index, 1).setText(os.path.splitext(comic)[0])
            metadata = comicParser.getMetadata(os.path.splitext(comic)[0])
            self.table_widget.setItem(index, 3, QTableWidgetItem())
            self.table_widget.item(index, 3).setText(metadata['year'])
            if 'author' and 'tags' and 'quality' in metadata:
                self.table_widget.setItem(index, 2, QTableWidgetItem())
                self.table_widget.item(index, 2).setText(metadata['author'])
                self.table_widget.setItem(index, 4, QTableWidgetItem())
                self.table_widget.item(index, 4).setText(metadata['tags'])
                self.table_widget.setItem(index, 5, QTableWidgetItem())
                self.table_widget.item(index, 5).setText(metadata['quality'])
            read_button = QPushButton(self.table_widget)
            self.table_widget.setCellWidget(index, 6, read_button)
            read_button.setText('Lire la BD')
            read_button.clicked.connect(self.make_read_comic(comic))
            edit_button = QPushButton(self.table_widget)
            self.table_widget.setCellWidget(index, 7, edit_button)
            edit_button.setText('Modifier les infos')
            edit_button.clicked.connect(self.make_open_edit_tab(comic))
예제 #29
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        self.homepage = kwargs["homepage"]
        del kwargs["homepage"]

        self.zeronet_base_url = kwargs["zeronet_base_url"]
        del kwargs["zeronet_base_url"]

        url = "%s/%s/" % (self.zeronet_base_url, self.homepage)

        if "url" in kwargs:
            url = kwargs["url"]
            del kwargs["url"]

        if "zeronet_path" in kwargs:
            self.zeronet_path = kwargs["zeronet_path"]
            del kwargs["zeronet_path"]

        super(MainWindow, self).__init__(*args, **kwargs)

        # Tabs
        self.tabs = QTabWidget()
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.close_tab)

        # New tab button
        #self.tab_add_button_index = self.tabs.addTab(QWidget(), '+')
        self.add_tab_button = QToolButton()
        self.add_tab_button.setText('+')
        self.add_tab_button.setStyleSheet(
            'QToolButton {border: none; margin: 4px 1ex 4px 0px; height: 480px; border-left: 1px solid lightgrey; padding: 0px 4px 0px 4px; font-weight: bold; color: #5d5b59}'
            'QToolButton:hover { background-color: lightgrey }'
            'QToolButton:pressed { background-color: grey }')
        self.add_tab_button.clicked.connect(self.new_tab_clicked)
        self.tabs.setCornerWidget(self.add_tab_button)

        # Navigation bar
        self.navigation = NavigationBar()
        self.navigation.url_bar.returnPressed.connect(self.navigate_to_url)

        # Back
        self.navigation.back_btn.triggered.connect(
            lambda: self.tabs.currentWidget().back())

        # Next
        self.navigation.next_btn.triggered.connect(
            lambda: self.tabs.currentWidget().forward())

        # Reload
        self.navigation.reload_btn.triggered.connect(
            lambda: self.tabs.currentWidget().reload())
        self.navigation.shortcut_reload.activated.connect(
            lambda: self.tabs.currentWidget().reload())
        self.navigation.shortcut_reload_f5.activated.connect(
            lambda: self.tabs.currentWidget().reload())

        # Home
        self.navigation.home_btn.triggered.connect(self.go_home)

        # Menu: Edit config action
        self.navigation.edit_config_action.triggered.connect(
            self.edit_zeronet_config_file)

        # Add new tab
        self.add_new_tab(url, "Home")

        # Get everything fitting in the main window
        self.addToolBar(self.navigation)
        self.setCentralWidget(self.tabs)
        self.show()
        self.setWindowTitle("ZeroNet Browser")
        self.setWindowIcon(QIcon("icons/zeronet-logo.svg"))
        self.showMaximized()

    def contextMenuEvent(self, event):
        print(event)

    def update_url_bar(self, q, browser=None):

        if browser != self.tabs.currentWidget():
            # If this signal is not from the current tab, ignore
            return

        url_array = q.toString().split('/')[3:]
        formatted_url = '/'.join(str(x) for x in url_array)
        self.navigation.url_bar.setText('zero://' + formatted_url)
        self.navigation.url_bar.setCursorPosition(0)

        if (self.tabs.currentWidget().can_go_back()):
            self.navigation.back_btn.setDisabled(False)
        else:
            self.navigation.back_btn.setDisabled(True)

        if (self.tabs.currentWidget().can_go_forward()):
            self.navigation.next_btn.setDisabled(False)
        else:
            self.navigation.next_btn.setDisabled(True)

    def navigate_to_url(self):
        # Get url
        url = self.navigation.url_bar.text()

        if url.startswith('zero://'):
            # ZeroNet protocol
            url_array = url.split('/')
            url = self.zeronet_base_url + '/' + url_array[2]
        elif url.startswith('http://') or url.startswith('https://'):
            # http protocol
            pass
        else:
            # Nothing mentionned
            url = self.zeronet_base_url + '/' + url

        self.tabs.currentWidget().setUrl(QUrl(url))

    def go_home(self):
        self.tabs.currentWidget().setUrl(
            QUrl("%s/%s/" % (self.zeronet_base_url, self.homepage)))

    def new_tab_clicked(self):
        self.add_new_tab("%s/%s/" % (self.zeronet_base_url, self.homepage),
                         "Home")

    def get_link_url_from_context_menu(self):
        tab = self.tabs.currentWidget()
        page = tab.page()
        context = page.contextMenuData()
        qurl = context.linkUrl()
        return qurl.url()

    def open_in_new_tab(self):
        url = self.get_link_url_from_context_menu()
        self.add_new_tab(url, "Home")

    # Doesnt feel right to have it here but it is working
    def open_in_new_window(self):
        url = self.get_link_url_from_context_menu()
        kwargs = {"url": url}
        self.window = self.__class__(**kwargs)

    def add_new_tab(self, qurl, label):
        # Instead of browser it should be called WebView !
        browser = Browser()

        # Triggered open in new tab
        openLinkInNewTabAction = browser.pageAction(
            QWebEnginePage.OpenLinkInNewTab)
        openLinkInNewWindowAction = browser.pageAction(
            QWebEnginePage.OpenLinkInNewWindow)
        openLinkInNewTabAction.triggered.connect(self.open_in_new_tab)
        openLinkInNewWindowAction.triggered.connect(self.open_in_new_window)
        self.addAction(openLinkInNewTabAction)

        browser.urlChanged.connect(
            lambda qurl, browser=browser: self.update_url_bar(qurl, browser))
        indexTab = self.tabs.addTab(browser, label)
        # Maybe change current index after loading?
        self.tabs.setCurrentIndex(indexTab)
        # We need to update the url !
        if qurl.startswith('zero://'):
            # ZeroNet protocol
            url_array = qurl.split('/')
            qurl = self.zeronet_base_url + '/' + url_array[2]
        elif qurl.startswith('http://') or qurl.startswith('https://'):
            # http protocol
            pass
        else:
            # Nothing mentionned
            qurl = self.zeronet_base_url + '/' + qurl

        currentTab = self.tabs.currentWidget()
        currentTab.loadFinished.connect(self.page_loaded)
        index = self.tabs.currentIndex()
        currentTab.titleChanged.connect(
            lambda title, index=index: self.tabs.setTabText(index, title))
        currentTab.iconChanged.connect(
            lambda icon, index=index: self.tabs.setTabIcon(index, icon))

        currentTab.setUrl(QUrl(qurl))
        return indexTab

    def page_loaded(self, ok):
        if ok:
            currentTab = self.tabs.currentWidget()
            index = self.tabs.currentIndex()
            label = currentTab.title()
            icon = currentTab.icon()
            self.tabs.setTabIcon(index, icon)
            self.tabs.setTabText(index, label)

    def close_tab(self, index):
        if self.tabs.count() == 1:
            self.tabs.currentWidget().setUrl(
                QUrl("%s/%s/" % (self.zeronet_base_url, self.homepage)))

            return
        self.tabs.removeTab(index)

    def edit_zeronet_config_file(self):
        filepath = os.path.join(os.sep, self.zeronet_path, "zeronet.conf")

        if sys.platform.startswith('darwin'):  # macOS
            subprocess.run(['open', filepath])
        elif sys.platform.startswith('win'):  # Windows
            os.startfile(filepath)
        else:  # linux variants
            subprocess.run(['xdg-open', filepath])
예제 #30
0
class MainWindow(QMainWindow):
    """[summary]
    Main window class containing the main window and its associated methods. 
    Args:
        QMainWindow (QObject): See qt documentation for more info.
    """
    # Send logging parameters to worker method
    logging_requested = QtCore.pyqtSignal(str, str, bool, str, object)

    def __init__(self, *args, **kwargs):
        """[summary]
        Function to initialise the Main Window, which will hold all the subsequent widgets to be created.
        """
        super(MainWindow, self).__init__(*args, **kwargs)

        self._tdc1_dev = None  # tdc1 device object
        self._dev_mode = ''  # 0 = 'singles', 1 = 'pairs', 3 = 'timestamp'
        self.device_path = ''  # Device path, eg. 'COM4'

        self.integration_time = 1
        self._logfile_name = ''  # Track the logfile(csv) being used by GUI
        self._ch_start = 1  # Start channel for pairs
        self._ch_stop = 3  # Stop channel for pairs
        self.plotSamples = 501  # Number of data points to plot

        self.log_flag = False  # Flag to track if data is being logged to csv file
        self.acq_flag = False  # Track if data is being acquired
        self._radio_flags = [
            0, 0, 0, 0
        ]  # Tracking which radio buttons are selected. All 0s by default

        self.logger = None  # Variable that will hold the logWorker object
        self.logger_thread = None  # Variable that will hold the QThread object

        self.initUI()  # UI is initialised afer the class variables are defined

        self._plot_tab = self.tabs.currentIndex(
        )  # Counts graph = 0, Coincidences graph = 1
        self.idx = min(len(self.y1), self.plotSamples)  # Index for plotting

    def initUI(self):
        """[summary]
        Contains all the UI elements and associated functionalities.
        """
        defaultFont = QtGui.QFont("Helvetica", 14)

        #---------Buttons---------#
        self.scanForDevice_Button = QtWidgets.QPushButton(
            "Scan for Device", self)
        self.scanForDevice_Button.clicked.connect(self.updateDevList)
        #self.scanForDevice_Button.setFixedSize(QSize(115, 35))

        self.liveStart_Button = QtWidgets.QPushButton("Live Start", self)
        self.liveStart_Button.clicked.connect(self.liveStart)
        #self.liveStart_Button.setFixedSize(QSize(115, 35))

        self.selectLogfile_Button = QtWidgets.QPushButton(
            "Select Logfile", self)
        self.selectLogfile_Button.clicked.connect(self.selectLogfile)
        #self.selectLogfile_Button.setFixedSize(QSize(115, 35))

        # setAutoExclusive method is used to toggle the radio buttons independently.
        self.radio1_Button = QRadioButton("Channel 1", self)
        self.radio1_Button.setStyleSheet('color: red; font-size: 14px')
        self.radio1_Button.setAutoExclusive(False)
        self.radio1_Button.toggled.connect(
            lambda: self.displayPlot1(self.radio1_Button))
        self.radio2_Button = QRadioButton("Channel 2", self)
        self.radio2_Button.setStyleSheet('color: green; font-size: 14px')
        self.radio2_Button.setAutoExclusive(False)
        self.radio2_Button.toggled.connect(
            lambda: self.displayPlot2(self.radio2_Button))
        self.radio3_Button = QRadioButton("Channel 3", self)
        self.radio3_Button.setStyleSheet('color: blue; font-size: 14px')
        self.radio3_Button.setAutoExclusive(False)
        self.radio3_Button.toggled.connect(
            lambda: self.displayPlot3(self.radio3_Button))
        self.radio4_Button = QRadioButton("Channel 4", self)
        self.radio4_Button.setStyleSheet('color: black; font-size: 14px')
        self.radio4_Button.setAutoExclusive(False)
        self.radio4_Button.toggled.connect(
            lambda: self.displayPlot4(self.radio4_Button))
        #---------Buttons---------#

        #---------Labels---------#
        #labelFontSize = "font-size: 18px"

        self.deviceLabel = QtWidgets.QLabel("Device:", self)
        self.deviceModeLabel = QtWidgets.QLabel("GUI Mode:", self)

        self.logfileLabel = QtWidgets.QLabel('', self)
        self.samplesLabel = QtWidgets.QLabel('Plot Samples:', self)
        self.integrationLabel = QtWidgets.QLabel("Integration time (ms):",
                                                 self)

        self.Ch1CountsLabel = QtWidgets.QLabel("0", self)
        self.Ch1CountsLabel.setStyleSheet("color: red; font-size: 128px")
        self.Ch1CountsLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.Ch2CountsLabel = QtWidgets.QLabel("0", self)
        self.Ch2CountsLabel.setStyleSheet("color: green; font-size: 128px")
        self.Ch2CountsLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.Ch3CountsLabel = QtWidgets.QLabel("0", self)
        self.Ch3CountsLabel.setStyleSheet("color: blue; font-size: 128px")
        self.Ch3CountsLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.Ch4CountsLabel = QtWidgets.QLabel("0", self)
        self.Ch4CountsLabel.setStyleSheet("color: black; font-size: 128px")
        self.Ch4CountsLabel.setAlignment(QtCore.Qt.AlignCenter)

        self.startChannelLabel = QtWidgets.QLabel("Start Channel:", self)
        self.stopChannelLabel = QtWidgets.QLabel("Stop Channel:", self)
        self.centerLabel = QtWidgets.QLabel("Center:", self)
        self.pairsRateLabel = QtWidgets.QLabel("Pairs/sec: <br>" + "0")
        self.pairsRateLabel.setStyleSheet("font-size: 64px")
        self.pairsRateLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.resolutionTextLabel = QtWidgets.QLabel("Bin Width:", self)
        #---------Labels---------#

        #---------Interactive Fields---------#
        self.integrationSpinBox = QSpinBox(self)
        self.integrationSpinBox.setRange(
            0, 65535)  # Max integration time based on tdc1 specs
        self.integrationSpinBox.setValue(1000)  # Default 1000ms = 1s
        self.integrationSpinBox.setKeyboardTracking(
            False
        )  # Makes sure valueChanged signal only fires when you want it to
        self.integrationSpinBox.valueChanged.connect(self.update_intTime)

        dev_list = serial_connection.search_for_serial_devices(
            tdc1.TimeStampTDC1.DEVICE_IDENTIFIER)
        self.devCombobox = QComboBox(self)
        self.devCombobox.addItem('Select your device')
        self.devCombobox.addItems(dev_list)
        self.devCombobox.currentTextChanged.connect(self.selectDevice)

        _dev_modes = ['singles', 'pairs']
        self.modesCombobox = QComboBox(self)
        self.modesCombobox.addItem('Select mode')
        self.modesCombobox.addItems(_dev_modes)
        self.modesCombobox.currentTextChanged.connect(self.selectDeviceMode)

        _channels = ['1', '2', '3', '4']
        self.channelsCombobox1 = QComboBox(self)
        self.channelsCombobox1.addItem('Select')
        self.channelsCombobox1.addItems(_channels)
        self.channelsCombobox1.setCurrentIndex(1)
        self.channelsCombobox1.currentTextChanged.connect(self.updateStart)
        self.channelsCombobox2 = QComboBox(self)
        self.channelsCombobox2.addItem('Select')
        self.channelsCombobox2.addItems(_channels)
        self.channelsCombobox2.setCurrentIndex(3)
        self.channelsCombobox2.currentTextChanged.connect(self.updateStop)

        self.samplesSpinbox = QSpinBox(self)
        self.samplesSpinbox.setRange(0, 501)
        self.samplesSpinbox.setValue(501)  # Default plot 501 data points
        self.samplesSpinbox.setKeyboardTracking(False)
        self.samplesSpinbox.valueChanged.connect(self.updatePlotSamples)

        self.centerSpinbox = QSpinBox(self)
        self.centerSpinbox.setRange(0, 1000)
        self.centerSpinbox.setKeyboardTracking(False)

        self.resolutionSpinbox = QSpinBox(self)
        self.resolutionSpinbox.setRange(0, 1000)
        self.resolutionSpinbox.setKeyboardTracking(False)
        self.resolutionSpinbox.valueChanged.connect(self.updateBins)
        #---------Interactive Fields---------#

        #---------PLOTS---------#
        # Initiating plot data variables
        # Plot 1 - Four channel counts plot
        self.x = []
        self.y1 = []
        self.y2 = []
        self.y3 = []
        self.y4 = []
        self.xnew = []
        self.y1new = []
        self.y2new = []
        self.y3new = []
        self.y4new = []
        self.y_data = [self.y1new, self.y2new, self.y3new, self.y4new]

        # Plot 2 - Time difference histogram (Channel cross-correlation)
        self.bins = 501
        self.binsize = 2  # milliseconds
        self.x0 = np.arange(0, self.bins * self.binsize, self.bins)
        self.y0 = np.zeros_like(self.x0)
        self.x0new = []
        self.y0new = []

        font = QtGui.QFont("Arial", 24)
        labelStyle = '<span style=\"color:black;font-size:25px\">'

        # Setting up plot window 1 (Plot Widget)
        self.tdcPlot = pg.PlotWidget(title="Counts Graph")
        self.tdcPlot.setBackground('w')
        self.tdcPlot.setLabel('left', labelStyle + 'Counts')
        self.tdcPlot.setLabel('bottom', labelStyle + 'Sample Number')
        self.tdcPlot.getAxis('left').tickFont = font
        self.tdcPlot.getAxis('bottom').tickFont = font
        self.tdcPlot.getAxis('bottom').setPen(color='k')
        self.tdcPlot.getAxis('left').setPen(color='k')
        self.tdcPlot.showGrid(y=True)

        # Setting up plot window 2 (Plot Widget)
        self.tdcPlot2 = pg.PlotWidget(title="Coincidences Histogram")
        self.tdcPlot2.setBackground('w')
        self.tdcPlot2.setLabel('left', labelStyle + 'Coincidences')
        self.tdcPlot2.setLabel('bottom', labelStyle + 'Time Delay')
        self.tdcPlot2.getAxis('left').tickFont = font
        self.tdcPlot2.getAxis('bottom').tickFont = font
        self.tdcPlot2.getAxis('bottom').setPen(color='k')
        self.tdcPlot2.getAxis('left').setPen(color='k')
        self.tdcPlot2.showGrid(y=True)

        # Setting up data plots (Plot data item)
        self.lineStyle1 = pg.mkPen(width=2, color='r')  # Red
        self.lineStyle2 = pg.mkPen(width=2, color='g')  # Green
        self.lineStyle3 = pg.mkPen(width=2, color='b')  # Blue
        self.lineStyle4 = pg.mkPen(width=2, color='k')  # Black
        self.lineStyle0 = pg.mkPen(width=1, color='r')

        # Plotting the graph - https://pyqtgraph.readthedocs.io/en/latest/plotting.html for organisation of plotting classes
        # Take note: multiple plotDataItems can sit on one plotWidget
        self.linePlot1 = self.tdcPlot.plot(self.x,
                                           self.y1,
                                           pen=self.lineStyle1)
        self.linePlot2 = self.tdcPlot.plot(self.x,
                                           self.y2,
                                           pen=self.lineStyle2)
        self.linePlot3 = self.tdcPlot.plot(self.x,
                                           self.y3,
                                           pen=self.lineStyle3)
        self.linePlot4 = self.tdcPlot.plot(self.x,
                                           self.y4,
                                           pen=self.lineStyle4)
        self.histogramPlot = self.tdcPlot2.plot(self.x0,
                                                self.y0,
                                                pen=self.lineStyle0,
                                                symbol='x',
                                                symbolPen='b',
                                                symbolBrush=0.2)
        self.linePlots = [
            self.linePlot1, self.linePlot2, self.linePlot3, self.linePlot4
        ]
        #---------PLOTS---------#

        #---------Main Window---------#
        self.setWindowTitle("TDC-1")
        #---------Main Window---------#

        #---------Tabs---------#
        self.tabs = QTabWidget()

        self.tab1 = QWidget()
        self.layout = QGridLayout()
        self.layout.addWidget(self.tdcPlot, 0, 0, 5, 5)
        self.layout.addWidget(self.Ch1CountsLabel, 0, 5)
        self.layout.addWidget(self.Ch2CountsLabel, 1, 5)
        self.layout.addWidget(self.Ch3CountsLabel, 2, 5)
        self.layout.addWidget(self.Ch4CountsLabel, 3, 5)
        self.tab1.setLayout(self.layout)
        self.tabs.addTab(self.tab1, "Counts")

        self.tab2 = QWidget()
        self.layout2 = QGridLayout()
        self.layout2.addWidget(self.tdcPlot2, 0, 0, 5, 5)
        self.layout2.addWidget(self.pairsRateLabel, 0, 5)
        self.tab2.setLayout(self.layout2)
        self.tabs.addTab(self.tab2, "Coincidences")
        self.tabs.currentChanged.connect(self.update_plot_tab)
        #---------Tabs---------#

        #Layout
        self.grid = QGridLayout()
        self.grid.setSpacing(20)
        self.grid.addWidget(self.deviceLabel, 0, 0)
        self.grid.addWidget(self.devCombobox, 0, 1)
        self.grid.addWidget(self.deviceModeLabel, 0, 2)
        self.grid.addWidget(self.modesCombobox, 0, 3, 1, 1)
        self.grid.addWidget(self.integrationLabel, 1, 0)
        self.grid.addWidget(self.integrationSpinBox, 1, 1)
        self.grid.addWidget(self.samplesLabel, 1, 2)
        self.grid.addWidget(self.samplesSpinbox, 1, 3, 1, 1)
        self.grid.addWidget(self.liveStart_Button, 2, 0)
        self.grid.addWidget(self.scanForDevice_Button, 2, 1)
        self.grid.addWidget(self.selectLogfile_Button, 2, 2)
        self.grid.addWidget(self.logfileLabel, 2, 3)
        self.grid.addWidget(self.tabs, 4, 0, 5, 4)

        self.singlesGroupbox = QGroupBox('Singles')
        self.singlesLayout = QHBoxLayout()
        self.singlesLayout.addWidget(self.radio1_Button)
        self.singlesLayout.addWidget(self.radio2_Button)
        self.singlesLayout.addWidget(self.radio3_Button)
        self.singlesLayout.addWidget(self.radio4_Button)
        self.singlesGroupbox.setLayout(self.singlesLayout)
        self.grid.addWidget(self.singlesGroupbox, 3, 0, 1, 2)

        self.pairsGroupbox = QGroupBox('Pairs')
        self.pairsSpinLayout = QHBoxLayout()
        self.pairsSpinLayout.addWidget(self.startChannelLabel)
        self.pairsSpinLayout.addWidget(self.channelsCombobox1)
        self.pairsSpinLayout.addWidget(self.stopChannelLabel)
        self.pairsSpinLayout.addWidget(self.channelsCombobox2)
        #self.pairsLabelLayout = QHBoxLayout()
        self.pairsCenterLayout = QHBoxLayout()
        self.pairsCenterLayout.addWidget(self.centerLabel)
        self.pairsCenterLayout.addWidget(self.centerSpinbox)
        self.pairsCenterLayout.addWidget(self.resolutionTextLabel)
        self.pairsCenterLayout.addWidget(self.resolutionSpinbox)
        self.pairsLayout = QVBoxLayout()
        #self.pairsLayout.addLayout(self.pairsLabelLayout)
        self.pairsLayout.addLayout(self.pairsSpinLayout)
        self.pairsLayout.addLayout(self.pairsCenterLayout)
        self.pairsGroupbox.setLayout(self.pairsLayout)
        self.grid.addWidget(self.pairsGroupbox, 3, 2, 1, 2)

        #Main Widget (on which the grid is to be implanted)
        self.mainwidget = QWidget()
        self.mainwidget.layout = self.grid
        self.mainwidget.setLayout(self.mainwidget.layout)
        self.mainwidget.setFont(defaultFont)
        self.setCentralWidget(self.mainwidget)

    # Connected to devComboBox.currentTextChanged
    @QtCore.pyqtSlot(str)
    def selectDevice(self, devPath: str):
        # Only allow resetting + changing device if not currently collecting data
        # Add msg box to allow user confirmation
        if self.acq_flag == False:
            self.StrongResetInternalVariables()
            self.resetDataAndPlots()
            self.resetGUIelements()
            if devPath != 'Select your device':
                self._tdc1_dev = tdc1.TimeStampTDC1(devPath)
                self.device_path = devPath

    @QtCore.pyqtSlot()
    def updateDevList(self):
        self.devCombobox.clear()
        self.devCombobox.addItem('Select your device')
        devices = serial_connection.search_for_serial_devices(
            tdc1.TimeStampTDC1.DEVICE_IDENTIFIER)
        self.devCombobox.addItems(devices)

    # Connected to modesCombobox.currentTextChanged
    @QtCore.pyqtSlot(str)
    def selectDeviceMode(self, newMode: str):
        # Only allow resetting + device mode change if not currently collecting data
        # Add msg box to allow user confirmation
        if self.acq_flag == False:
            self.WeakResetInternalVariables()
            self.resetDataAndPlots()
            self.resetGUIelements()
            if newMode != 'Select mode':
                if self._tdc1_dev == None:
                    self._tdc1_dev = tdc1.TimeStampTDC1(self.device_path)
                self._tdc1_dev.mode = newMode  # Setting tdc1 mode with @setter
                self._dev_mode = newMode

    # Update plot index on plot tab change
    @QtCore.pyqtSlot()
    def update_plot_tab(self):
        self._plot_tab = self.tabs.currentIndex()

    # Update integration time on spinbox value change
    @QtCore.pyqtSlot(int)
    def update_intTime(self, int_time: int):
        # Convert to seconds
        self.integration_time = int_time * 1e-3
        if self.logger:
            self.logger.int_time = int_time * 1e-3

    @QtCore.pyqtSlot(int)
    def updatePlotSamples(self, samples: int):
        self.plotSamples = samples

    # Click Live Start button to get started!
    @QtCore.pyqtSlot()
    # Connected to self.liveStart_button.clicked
    def liveStart(self):
        #If currently live plotting
        if self.acq_flag is True and self.liveStart_Button.text(
        ) == "Live Stop":
            self.acq_flag = False
            self.logger.active_flag = False  # To stop logger from looping
            self.selectLogfile_Button.setEnabled(True)
            self.liveStart_Button.setText("Live Start")
            time.sleep(1)  # Pause to let all loops end
            self._tdc1_dev = None  # Destroy tdc1_dev object
            self.logger = None  # Destroy logger
            self.logger_thread = None  # and thread...?
        #If not currently live plotting
        elif self.acq_flag is False and self.liveStart_Button.text(
        ) == "Live Start":
            if self._tdc1_dev == None:
                self._tdc1_dev = tdc1.TimeStampTDC1(
                    self.devCombobox.currentText())
            self.acq_flag = True
            self.resetDataAndPlots()
            self.selectLogfile_Button.setEnabled(False)
            self.modesCombobox.setEnabled(True)
            self.liveStart_Button.setText("Live Stop")
            self.startLogging()

    # Logging
    def startLogging(self):
        """[summary]
        Creation process of worker object and QThread.
        """
        # Create worker instance and a thread
        self.logger = logWorker()
        self.logger_thread = QtCore.QThread(
            self)  # QThread is not a thread, but a thread MANAGER

        # Assign worker to the thread and start the thread
        self.logger.moveToThread(self.logger_thread)
        self.logger_thread.start(
        )  # This is where the thread is actually created, I think

        # Connect signals and slots AFTER moving the object to the thread
        self.logging_requested.connect(self.logger.log_which_data)
        self.logger.data_is_logged.connect(self.update_data_from_thread)
        self.logger.histogram_logged.connect(self.updateHistogram)

        self.logger.int_time = int(
            self.integrationSpinBox.text()) * 1e-3  # Convert to seconds
        #self.log_flag = True
        self.logging_requested.emit(self._logfile_name, self.device_path, self.log_flag, self._dev_mode, \
            self._tdc1_dev)

    @QtCore.pyqtSlot()
    def selectLogfile(self):
        if self.acq_flag == False:
            if self.selectLogfile_Button.text() == 'Select Logfile':
                default_filetype = 'csv'
                start = datetime.now().strftime(
                    "%Y%m%d_%Hh%Mm%Ss ") + "_TDC1." + default_filetype
                self._logfile_name = QtGui.QFileDialog.getSaveFileName(
                    self, "Save to log file", start)[0]
                self.logfileLabel.setText(self._logfile_name)
                if self._logfile_name != '':
                    #self.startLogging_Button.setEnabled(True)
                    self.log_flag = True
                    self.selectLogfile_Button.setText('Unselect Logfile')
            elif self.selectLogfile_Button.text() == 'Unselect Logfile':
                self.logfileLabel.setText('')
                self.selectLogfile_Button.setText('Select Logfile')

    # Updating data
    # Connected to data_is_logged signal
    @QtCore.pyqtSlot(tuple, str, list)
    def update_data_from_thread(self, data: tuple, dev_mode: str,
                                radio_flags: list):
        if len(self.x) == PLT_SAMPLES:
            self.x = self.x[1:]
            self.x.append(self.x[-1] + 1)
            self.y1 = self.y1[1:]
            self.y2 = self.y2[1:]
            self.y3 = self.y3[1:]
            self.y4 = self.y4[1:]
        else:
            self.x.append(len(self.x) +
                          1)  # Takes care of empty list case as well
        self.y1.append(data[0])
        self.y2.append(data[1])
        self.y3.append(data[2])
        self.y4.append(data[3])
        self.idx = min(len(self.y1), self.plotSamples)
        self.y1new = self.y1[-self.idx:]
        self.y2new = self.y2[-self.idx:]
        self.y3new = self.y3[-self.idx:]
        self.y4new = self.y4[-self.idx:]
        self.y_data = [self.y1new, self.y2new, self.y3new, self.y4new]
        self._radio_flags = radio_flags
        self.Ch1CountsLabel.setText(str(data[0]))
        self.Ch2CountsLabel.setText(str(data[1]))
        self.Ch3CountsLabel.setText(str(data[2]))
        self.Ch4CountsLabel.setText(str(data[3]))
        self.updatePlots(self._radio_flags)

    # Updating plots 1-4
    def updatePlots(self, radio_flags: list):
        for i in range(len(radio_flags)):
            if radio_flags[i] == 1:
                self.linePlots[i].setData(self.x[-self.idx:],
                                          self.y_data[i][-self.idx:])

    # Radio button slots (functions)
    @QtCore.pyqtSlot('PyQt_PyObject')
    def displayPlot1(self, b: QRadioButton):
        if self.acq_flag == True:
            if b.isChecked() == True:
                # Possible to clear self.x and self.y1 without disrupting the worker loop?
                self.updatePlots(self._radio_flags)
                self.linePlot1.setPen(self.lineStyle1)
                self.logger.radio_flags[0] = 1
                self._radio_flags[0] = 1
            elif b.isChecked() == False:
                self.linePlot1.setPen(None)
                self.logger.radio_flags[0] = 0
                self._radio_flags[0] = 0

    @QtCore.pyqtSlot('PyQt_PyObject')
    def displayPlot2(self, b: QRadioButton):
        if self.acq_flag == True:
            if b.isChecked() == True:
                self.updatePlots(self._radio_flags)
                self.linePlot2.setPen(self.lineStyle2)
                self.logger.radio_flags[1] = 1
                self._radio_flags[1] = 1
            elif b.isChecked() == False:
                self.linePlot2.setPen(None)
                self.logger.radio_flags[1] = 0
                self._radio_flags[1] = 0

    @QtCore.pyqtSlot('PyQt_PyObject')
    def displayPlot3(self, b: QRadioButton):
        if self.acq_flag == True:
            if b.isChecked() == True:
                self.updatePlots(self._radio_flags)
                self.linePlot3.setPen(self.lineStyle3)
                self.logger.radio_flags[2] = 1
                self._radio_flags[2] = 1
            elif b.isChecked() == False:
                self.linePlot3.setPen(None)
                self.logger.radio_flags[2] = 0
                self._radio_flags[2] = 0

    @QtCore.pyqtSlot('PyQt_PyObject')
    def displayPlot4(self, b: QRadioButton):
        if self.acq_flag == True:
            if b.isChecked():
                self.updatePlots(self._radio_flags)
                self.linePlot4.setPen(self.lineStyle4)
                self.logger.radio_flags[3] = 1
                self._radio_flags[3] = 1
            elif b.isChecked() == False:
                self.linePlot4.setPen(None)
                self.logger.radio_flags[3] = 0
                self._radio_flags[3] = 0

    @QtCore.pyqtSlot(str)
    def updateStart(self, channel: str):
        cs = int(channel)
        if self.acq_flag == True and self.modesCombobox.currentText(
        ) == "pairs":
            self._ch_start = cs
            if self.logger:
                self.logger.ch_start = cs

    @QtCore.pyqtSlot(str)
    def updateStop(self, channel: str):
        cs = int(channel)
        if self.acq_flag == True and self.modesCombobox.currentText(
        ) == "pairs":
            self._ch_stop = cs
            if self.logger:
                self.logger.ch_stop = cs

    # Histogram
    # Connected to histogram_logged signal
    def updateHistogram(self, g2_data: dict):
        # {int - ch_start counts, int- ch_stop counts, int - actual acq time, float - time bins, float - histogram values}
        # time bins and histogram vals are both np arrays
        incremental_y = g2_data['histogram']
        incremental_y_int = incremental_y.astype(np.int32)
        self.y0 += incremental_y_int
        center = self.centerSpinbox.currentValue()
        idx = int(-(-center //
                    self.binsize))  # Upside-down floor div aka ceiling div
        startidx = idx - idx_width
        stopidx = idx + idx_width
        try:
            self.x0new = self.x0[startidx:stopidx]
            self.y0new = self.y0[startidx:stopidx]
        # If startidx is negative
        except IndexError:
            try:
                self.x0new = self.x0[:stopidx]
                self.y0new = self.y0[:stopidx]
            except IndexError:
                try:
                    self.x0new = self.x0[startidx:]
                    self.y0new = self.y0[startidx:]
                except:
                    pass
        self.histogramPlot.setData(self.x0new, self.y0new)
        totalpairs = np.sum(self.y0, dtype=np.int32)
        self.pairsRateLabel.setText("<font size=24>Pairs/sec: </font><br>" +
                                    "<font size=96>" + totalpairs + "</font>")

    # Reserve in case above func fails
    # def updateHistogram(self, g2_data: dict):
    #     # {int - ch_start counts, int- ch_stop counts, int - actual acq time, float - time bins, float - histogram values}
    #     # time bins and histogram vals are both np arrays
    #     incremental_y = g2_data['histogram']
    #     incremental_y_int = incremental_y.astype(np.int32)
    #     self.y0 += incremental_y_int
    #     self.idx = min(len(self.y0), self.plotSamples)
    #     self.x0new = self.x0[:(self.idx)]
    #     self.y0new = self.y0[:(self.idx)]
    #     self.histogramPlot.setData(self.x0new, self.y0new)
    #     totalpairs = np.sum(self.y0, dtype=np.int32)
    #     self.pairsRateLabel.setText("<font size=24>Pairs/sec: </font><br>" + "<font size=96>" + totalpairs + "</font>")

    @QtCore.pyqtSlot(int)
    def updateBins(self, bin_width):
        self.binsize = bin_width
        self.x0 = np.arange(0, self.bins * self.binsize, self.binsize)

    # For future use
    def StrongResetInternalVariables(self):
        self.integration_time = 1
        self._logfile_name = ''  # Track the logfile(csv) being used by GUI
        self.resetWorkerAndThread()

        self._tdc1_dev = None  # tdc1 device object
        self._dev_mode = ''  # 0 = 'singles', 1 = 'pairs', 3 = 'timestamp'
        self.device_path = ''  # Device path, eg. 'COM4'

    def WeakResetInternalVariables(self):
        # Excludes resetting variables relating to the device object (device, mode, path)
        self.integration_time = 1
        self._logfile_name = ''  # Track the logfile(csv) being used by GUI
        self.resetWorkerAndThread()

    def resetWorkerAndThread(self):
        time.sleep(2)  # To allow threads to end
        self.logger = None
        self.logger_thread = None

    # For future use
    def resetGUIelements(self):
        self.liveStart_Button.setEnabled(True)
        self.selectLogfile_Button.setEnabled(True)
        self.logfileLabel.setText('')
        self.radio1_Button.setChecked(False)
        self.radio2_Button.setChecked(False)
        self.radio3_Button.setChecked(False)
        self.radio4_Button.setChecked(False)
        self.integrationSpinBox.setValue(1000)
        self.samplesSpinbox.setValue(501)

    def resetDataAndPlots(self):
        self.x0 = np.arange(0, self.bins * self.binsize, self.binsize)
        self.y0 = np.zeros_like(self.x0)
        self.x0new = []
        self.y0new = []
        self.x = []
        self.y1 = []
        self.y2 = []
        self.y3 = []
        self.y4 = []
        self.xnew = []
        self.y1new = []
        self.y2new = []
        self.y3new = []
        self.y4new = []
        self.linePlot1.setData(self.x, self.y1)
        self.linePlot2.setData(self.x, self.y2)
        self.linePlot3.setData(self.x, self.y3)
        self.linePlot4.setData(self.x, self.y4)
        self.histogramPlot.setData(self.x0, self.y0)
        self.radio1_Button.setChecked(False)
        self.radio2_Button.setChecked(False)
        self.radio3_Button.setChecked(False)
        self.radio4_Button.setChecked(False)
        self._radio_flags = [0, 0, 0, 0]
예제 #31
0
class mainwindow(QWidget):
    def __init__(self, username, dataoptions, driver, semesters):
        self.username = username
        self.dataoptions = dataoptions
        self.driver = driver
        self.semesters = semesters
        self.subThread = submitThread(self)
        self.subThread.finished.connect(self.completed)
        super().__init__()

        self.initUI()

    def initUI(self):
        self.center()

        #add the data type label and C C C combobox
        self.datatypelabel = QLabel(self)
        self.datatypelabel.setText("Data Pull Type")
        self.datatypelabel.setAlignment(Qt.AlignCenter)

        self.datacombo = QComboBox(self)
        #Sorted by alphabet
        self.datacombo.addItems(sorted(self.dataoptions.keys()))
        self.datacombo.currentTextChanged.connect(self.combochange)

        #add the filter label
        self.filterlabel = QLabel(self)
        self.filterlabel.setText('Filters')
        self.filterlabel.setAlignment(Qt.AlignCenter)

        #add all of the other filter things
        self.usernamelabel = QLabel(self)
        self.usernamelabel.setText("Created By: ")

        self.usernamecombo = QComboBox(self)

        self.assignedlabel = QLabel(self)
        self.assignedlabel.setText("Assigned To: ")

        self.assignedcombo = QComboBox(self)

        self.locationlabel = QLabel(self)
        self.locationlabel.setText("Location: ")

        self.locationcombo = QComboBox(self)

        self.categorylabel = QLabel(self)
        self.categorylabel.setText("Category: ")

        self.categorycombo = QComboBox(self)
        self.statuslabels = QLabel(self)
        self.statuslabels.setText("Status: ")

        self.statuscombo = QComboBox(self)

        #add the startdate and end date calendars
        self.startcal = QCalendarWidget(self)
        self.startcal.setSelectedDate(date.today() - timedelta(days=30))
        self.startcal.setVerticalHeaderFormat(QCalendarWidget.NoVerticalHeader)
        self.startcal.setGridVisible(True)
        self.startcal.clicked.connect(self.startdatechange)

        self.startlabel = QLabel(self)
        self.startlabel.setText("Start Date: " +
                                self.startcal.selectedDate().toString())

        self.startdroplabel = QLabel(self)
        self.startdroplabel.setText('Autoselect start of :  ')
        self.startdroplabel.setObjectName('desctext')

        self.startcombo = QComboBox(self)
        self.startcombo.addItems(self.semesters.keys())
        self.startcombo.currentTextChanged.connect(self.startcomboselect)

        self.endcal = QCalendarWidget(self)
        self.endcal.setSelectedDate(date.today())
        self.endcal.setVerticalHeaderFormat(QCalendarWidget.NoVerticalHeader)
        self.endcal.setGridVisible(True)
        self.endcal.clicked.connect(self.enddatechange)

        self.endlabel = QLabel(self)
        self.endlabel.setText("End Date: " +
                              self.endcal.selectedDate().toString())

        self.enddroplabel = QLabel(self)
        self.enddroplabel.setText('Autoselect end of :  ')
        self.enddroplabel.setObjectName('desctext')

        self.endcombo = QComboBox(self)
        self.endcombo.addItems(self.semesters.keys())
        self.endcombo.currentTextChanged.connect(self.endcomboselect)

        #create the maxreturns things
        self.maxlabel = QLabel(self)
        self.maxlabel.setText("Max Returns: ")
        self.maxlabel.hide()

        self.maxbox = QLineEdit(self)
        self.maxbox.setText('10000000')
        self.maxbox.hide()

        #add close button
        self.closebutton = QPushButton('Close', self)
        self.closebutton.clicked.connect(self.close)

        #add submit button
        self.submitbutton = QPushButton('Submit', self)
        self.submitbutton.clicked.connect(self.subThread.start)

        self.tabs = QTabWidget()

        #everything for the data pull tab
        self.datapulltab = QWidget()

        datatypelabhbox = QHBoxLayout()
        datatypelabhbox.addWidget(self.datatypelabel)

        datatypehbox = QHBoxLayout()
        datatypehbox.addWidget(self.datacombo)

        filternamehbox = QHBoxLayout()
        filternamehbox.addWidget(self.filterlabel)

        usernamehbox = QHBoxLayout()
        usernamehbox.addWidget(self.usernamelabel)

        assignedhbox = QHBoxLayout()
        assignedhbox.addWidget(self.assignedlabel)

        locationhbox = QHBoxLayout()
        locationhbox.addWidget(self.locationlabel)

        categoryhbox = QHBoxLayout()
        categoryhbox.addWidget(self.categorylabel)

        statushbox = QHBoxLayout()
        statushbox.addWidget(self.statuslabels)

        dataselectlayout = QVBoxLayout()
        dataselectlayout.addLayout(datatypelabhbox)
        dataselectlayout.addLayout(datatypehbox)
        verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                     QSizePolicy.Expanding)
        dataselectlayout.addSpacerItem(verticalSpacer)
        dataselectlayout.addLayout(filternamehbox)
        dataselectlayout.addLayout(usernamehbox)
        dataselectlayout.addWidget(self.usernamecombo)
        dataselectlayout.addLayout(assignedhbox)
        dataselectlayout.addWidget(self.assignedcombo)
        dataselectlayout.addLayout(locationhbox)
        dataselectlayout.addWidget(self.locationcombo)
        dataselectlayout.addLayout(categoryhbox)
        dataselectlayout.addWidget(self.categorycombo)
        dataselectlayout.addLayout(statushbox)
        dataselectlayout.addWidget(self.statuscombo)
        dataselectlayout.setSpacing(3)
        dataselectlayout.addStretch(1)

        startdrophlayout = QHBoxLayout()
        startdrophlayout.addWidget(self.startdroplabel)
        startdrophlayout.addWidget(self.startcombo)
        startdrophlayout.setSpacing(0)
        startdrophlayout.addStretch(0)

        enddropylayout = QHBoxLayout()
        enddropylayout.addWidget(self.enddroplabel)
        enddropylayout.addWidget(self.endcombo)
        enddropylayout.setSpacing(0)
        enddropylayout.addStretch(0)

        calendarlayout = QVBoxLayout()
        calendarlayout.addWidget(self.startlabel)
        calendarlayout.addLayout(startdrophlayout)
        calendarlayout.addWidget(self.startcal)
        calendarlayout.addSpacing(10)
        calendarlayout.addWidget(self.endlabel)
        calendarlayout.addLayout(enddropylayout)
        calendarlayout.addWidget(self.endcal)
        calendarlayout.setSpacing(3)
        calendarlayout.addStretch(1)

        datapullhlayout = QHBoxLayout()
        datapullhlayout.addLayout(dataselectlayout)
        datapullhlayout.addSpacing(10)
        datapullhlayout.addLayout(calendarlayout)

        datapullvlayout = QVBoxLayout()
        datapullvlayout.addSpacing(15)
        datapullvlayout.addLayout(datapullhlayout)

        self.datapulltab.setLayout(datapullvlayout)

        #Report things?

        self.reporttab = QWidget()

        self.startrepcal = QCalendarWidget(self)
        self.startrepcal.setSelectedDate(date.today() - timedelta(days=30))
        self.startrepcal.setVerticalHeaderFormat(
            QCalendarWidget.NoVerticalHeader)
        self.startrepcal.setGridVisible(True)
        self.startrepcal.clicked.connect(self.startrepdatechange)

        self.startreplabel = QLabel(self)
        self.startreplabel.setText("Start Date: " +
                                   self.startrepcal.selectedDate().toString())

        self.endrepcal = QCalendarWidget(self)
        self.endrepcal.setSelectedDate(date.today())
        self.endrepcal.setVerticalHeaderFormat(
            QCalendarWidget.NoVerticalHeader)
        self.endrepcal.setGridVisible(True)
        self.endrepcal.clicked.connect(self.endrepdatechange)

        self.endreplabel = QLabel(self)
        self.endreplabel.setText("End Date: " +
                                 self.endrepcal.selectedDate().toString())

        self.reporttypelabel = QLabel(self)
        self.reporttypelabel.setText('Report Type')
        self.reporttypelabel.setAlignment(Qt.AlignCenter)

        self.reportdrop = QComboBox(self)
        self.reportdrop.addItems([x.name for x in report.report_list])
        self.reportdrop.currentTextChanged.connect(self.reportcombochange)

        self.reportactivelabel = QLabel(self)
        self.reportactivelabel.setText("Active")

        self.reportactive = QLabel(self)
        self.reportactive.setText("")
        self.reportactive.setObjectName('desctext')

        self.reportauthorlabel = QLabel(self)
        self.reportauthorlabel.setText("Author")

        self.reportauthor = QLabel(self)
        self.reportauthor.setText("")
        self.reportauthor.setObjectName('desctext')

        self.reportdesclabel = QLabel(self)
        self.reportdesclabel.setText("Report Description")

        self.descbox = QLabel(self)
        self.descbox.setText("")
        self.descbox.setWordWrap(True)
        self.descbox.setFixedWidth(self.usernamecombo.frameGeometry().width() +
                                   53)
        self.descbox.setObjectName('desctext')

        self.startrepdroplabel = QLabel(self)
        self.startrepdroplabel.setObjectName('desctext')
        self.startrepdroplabel.setText('Autoselect start of :  ')

        self.startrepcombo = QComboBox(self)
        self.startrepcombo.addItems(self.semesters.keys())
        self.startrepcombo.currentTextChanged.connect(self.startrepcomboselect)

        self.enddropreplabel = QLabel(self)
        self.enddropreplabel.setText('Autoselect end of :  ')
        self.enddropreplabel.setObjectName('desctext')

        self.endrepcombo = QComboBox(self)
        self.endrepcombo.addItems(self.semesters.keys())
        self.endrepcombo.currentTextChanged.connect(self.endrepcomboselect)

        newreportlayout = QVBoxLayout()

        newreportlayout.addWidget(self.reporttypelabel)
        newreportlayout.addWidget(self.reportdrop)
        verticalSpacernew = QSpacerItem(10, 20, QSizePolicy.Minimum,
                                        QSizePolicy.Expanding)
        newreportlayout.addSpacerItem(verticalSpacernew)
        newreportlayout.addWidget(self.reportauthorlabel)
        newreportlayout.addWidget(self.reportauthor)
        verticalSpacernewest = QSpacerItem(10, 20, QSizePolicy.Minimum,
                                           QSizePolicy.Expanding)
        newreportlayout.addSpacerItem(verticalSpacernewest)
        newreportlayout.addWidget(self.reportactivelabel)
        newreportlayout.addWidget(self.reportactive)
        verticalSpacernewer = QSpacerItem(10, 20, QSizePolicy.Minimum,
                                          QSizePolicy.Expanding)
        newreportlayout.addSpacerItem(verticalSpacernewer)
        newreportlayout.addWidget(self.reportdesclabel)
        newreportlayout.addWidget(self.descbox)
        newreportlayout.setSpacing(3)
        newreportlayout.addStretch(1)

        startrepdrophlayout = QHBoxLayout()
        startrepdrophlayout.addWidget(self.startrepdroplabel)
        startrepdrophlayout.addWidget(self.startrepcombo)
        startrepdrophlayout.setSpacing(0)
        startrepdrophlayout.addStretch(0)

        endrepdropylayout = QHBoxLayout()
        endrepdropylayout.addWidget(self.enddropreplabel)
        endrepdropylayout.addWidget(self.endrepcombo)
        endrepdropylayout.setSpacing(0)
        endrepdropylayout.addStretch(0)

        repcallayout = QVBoxLayout()
        repcallayout.addWidget(self.startreplabel)
        repcallayout.addLayout(startrepdrophlayout)
        repcallayout.addWidget(self.startrepcal)
        repcallayout.addSpacing(10)
        repcallayout.addWidget(self.endreplabel)
        repcallayout.addLayout(endrepdropylayout)
        repcallayout.addWidget(self.endrepcal)
        repcallayout.setSpacing(3)
        repcallayout.addStretch(1)

        reportouterlayout = QHBoxLayout()
        reportouterlayout.addLayout(newreportlayout)
        reportouterlayout.addSpacing(10)
        reportouterlayout.addLayout(repcallayout)

        reportouterlayoutout = QVBoxLayout()
        reportouterlayoutout.addSpacing(15)
        reportouterlayoutout.addLayout(reportouterlayout)
        self.reporttab.setLayout(reportouterlayoutout)

        self.tabs.addTab(self.datapulltab, "Data Pull")
        self.tabs.addTab(self.reporttab, "Reporting")

        buttonlayout = QHBoxLayout()
        buttonlayout.addWidget(self.closebutton)
        buttonlayout.addWidget(self.submitbutton)

        self.statuslabel = QLabel(self)
        self.statuslabel.setText("Ready")
        self.statuslabel.setObjectName('statuslabel')
        self.statuslabel.setAlignment(Qt.AlignRight)

        outerlayout = QVBoxLayout()
        outerlayout.addWidget(self.tabs)
        outerlayout.addSpacing(15)
        outerlayout.addLayout(buttonlayout)
        outerlayout.addWidget(self.statuslabel)
        self.setLayout(outerlayout)

        self.current_report = False
        self.dframe = False

        self.reportcombochange()
        self.combochange()
        self.setWindowTitle('PIEthon: logged in as ' + self.username)
        self.setWindowIcon(
            QIcon(functions.resource_path('resources\\PIEcon.png')))

        #style things
        self.setStyleSheet(
            open(functions.resource_path("resources\\iu_stylesheet.qss"),
                 "r").read())
        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def statusUpdate(self, newstat):
        #print('in status update')
        self.statuslabel.setText(newstat)
        QCoreApplication.processEvents()

    def startdatechange(self):
        self.startcombo.setCurrentIndex(0)
        self.startlabel.setText("Start Date:  " +
                                self.startcal.selectedDate().toString())
        self.startreplabel.setText("Start Date:  " +
                                   self.startcal.selectedDate().toString())
        self.startrepcal.setSelectedDate(self.startcal.selectedDate())

    def enddatechange(self):
        self.endcombo.setCurrentIndex(0)
        self.endlabel.setText("End Date:  " +
                              self.endcal.selectedDate().toString())
        self.endreplabel.setText("End Date:  " +
                                 self.endcal.selectedDate().toString())
        self.endrepcal.setSelectedDate(self.endcal.selectedDate())

    def startrepdatechange(self):
        self.startrepcombo.setCurrentIndex(0)
        self.startreplabel.setText("Start Date:  " +
                                   self.startrepcal.selectedDate().toString())
        self.startlabel.setText("Start Date:  " +
                                self.startrepcal.selectedDate().toString())
        self.startcal.setSelectedDate(self.startrepcal.selectedDate())

    def endrepdatechange(self):
        self.endrepcombo.setCurrentIndex(0)
        self.endreplabel.setText("End Date:  " +
                                 self.endrepcal.selectedDate().toString())
        self.endlabel.setText("End Date:  " +
                              self.endrepcal.selectedDate().toString())
        self.endcal.setSelectedDate(self.endrepcal.selectedDate())

    def startcomboselect(self):
        self.startrepcombo.setCurrentIndex(self.startcombo.currentIndex())
        conv = self.semesters[self.startcombo.currentText()].getStart()
        if conv == '':
            return
        self.startlabel.setText("Start Date:  " + conv.strftime('%a %b %d %Y'))
        self.startreplabel.setText("Start Date:  " +
                                   conv.strftime('%a %b %d %Y'))
        self.startcal.setSelectedDate(conv)
        self.startrepcal.setSelectedDate(conv)

    def endcomboselect(self):
        self.endrepcombo.setCurrentIndex(self.endcombo.currentIndex())
        conv = self.semesters[self.endcombo.currentText()].getEnd()
        if conv == '':
            return
        self.endlabel.setText("End Date:  " + conv.strftime('%a %b %d %Y'))
        self.endreplabel.setText("End Date:  " + conv.strftime('%a %b %d %Y'))
        self.endcal.setSelectedDate(conv)
        self.endrepcal.setSelectedDate(conv)

    def startrepcomboselect(self):
        self.startcombo.setCurrentIndex(self.startrepcombo.currentIndex())
        conv = self.semesters[self.startrepcombo.currentText()].getStart()
        if conv == '':
            return
        self.startreplabel.setText("Start Date:  " +
                                   conv.strftime('%a %b %d %Y'))
        self.startlabel.setText("Start Date:  " + conv.strftime('%a %b %d %Y'))
        self.startrepcal.setSelectedDate(conv)
        self.startcal.setSelectedDate(conv)

    def endrepcomboselect(self):
        self.endcombo.setCurrentIndex(self.endrepcombo.currentIndex())
        conv = self.semesters[self.endrepcombo.currentText()].getEnd()
        if conv == '':
            return
        self.endreplabel.setText("End Date:  " + conv.strftime('%a %b %d %Y'))
        self.endlabel.setText("End Date:  " + conv.strftime('%a %b %d %Y'))
        self.endrepcal.setSelectedDate(conv)
        self.endcal.setSelectedDate(conv)

    def reportcombochange(self):
        self.current_report = report.report_list[
            self.reportdrop.currentIndex()]
        self.descbox.setText(self.current_report.description)
        self.reportactive.setText(str(self.current_report.active))
        self.reportauthor.setText(str(self.current_report.author))

    def combochange(self):
        datatype = self.dataoptions.get(self.datacombo.currentText())

        if (datatype is None):
            return

        if (len(datatype.createdbyDict) > 1):
            self.usernamecombo.clear()
            self.usernamecombo.addItems(datatype.createdbyDict.keys())
            self.usernamecombo.setEnabled(True)
            if datatype.createdbyPost:
                self.usernamelabel.setText("Created By (POST): ")
            else:
                self.usernamelabel.setText("Created By: ")
        else:
            self.usernamelabel.setText("Created By: ")
            self.usernamecombo.clear()
            self.usernamecombo.setEnabled(False)

        if (len(datatype.locationDict) > 1):
            self.locationcombo.clear()
            self.locationcombo.addItems(datatype.locationDict.keys())
            self.locationcombo.setEnabled(True)
            if datatype.locationPost:
                self.locationlabel.setText("Location (POST): ")
            else:
                self.locationlabel.setText("Location: ")
        else:
            self.locationlabel.setText("Location: ")
            self.locationcombo.clear()
            self.locationcombo.setEnabled(False)

        if (len(datatype.statusDict) > 1):
            self.statuscombo.clear()
            self.statuscombo.addItems(datatype.statusDict)
            self.statuscombo.setEnabled(True)
            if datatype.statusPost:
                self.statuslabels.setText("Status (POST):")
            else:
                self.statuslabels.setText("Status:")
        else:
            self.statuslabels.setText("Status:")
            self.statuscombo.clear()
            self.statuscombo.setEnabled(False)

        if (len(datatype.categoryDict) > 1):
            self.categorycombo.clear()
            self.categorycombo.addItems(datatype.categoryDict.keys())
            self.categorycombo.setEnabled(True)
            if datatype.categoryPost:
                self.categorylabel.setText("Category (POST):")
            else:
                self.categorylabel.setText("Category:")
        else:
            self.categorylabel.setText("Category:")
            self.categorycombo.clear()
            self.categorycombo.setEnabled(False)

        if (len(datatype.assignedToDict) > 1):
            self.assignedcombo.clear()
            self.assignedcombo.addItems(datatype.assignedToDict.keys())
            self.assignedcombo.setEnabled(True)
            if datatype.assignedToPost:
                self.assignedlabel.setText("Assigned To (POST):")
            else:
                self.assignedlabel.setText("Assigned To:")
        else:
            self.assignedlabel.setText("Assigned To:")
            self.assignedcombo.clear()
            self.assignedcombo.setEnabled(False)

        self.endcal.setEnabled(datatype.allowDates)
        self.startcal.setEnabled(datatype.allowDates)
        self.startcombo.setEnabled(datatype.allowDates)
        self.endcombo.setEnabled(datatype.allowDates)

    def completed(self):
        self.statusUpdate('Ready')
        self.current_report.reset()
        if self.datecheck() or self.dframe is False:
            return
        if (self.tabs.currentIndex() == 0):
            self.mainwind = previewGui.preview(
                self.dframe, self.datacombo.currentText(),
                self.startcal.selectedDate().toPyDate(),
                self.endcal.selectedDate().toPyDate())
            self.mainwind.show()
        self.dframe = False
        self.dataoptions.get(self.datacombo.currentText()).reset()
        self.current_report.reset()
        self.statusUpdate('Ready')

    def datecheck(self):
        return ((self.startcal.selectedDate().daysTo(
            self.endcal.selectedDate()) < 0)
                or (self.startrepcal.selectedDate().daysTo(
                    self.endrepcal.selectedDate()) < 0))
예제 #32
0
class SearchView(QWidget):
    def __init__(self):
        super(SearchView, self).__init__()
        self._rowCount = 20
        self._table = {}
        self._lock = threading.Lock()
        self.__initView__()
        self._searchEdit.setFocus()

    def __initView__(self):
        grid = QVBoxLayout(self)
        grid.addLayout(self.__initHead__(), Qt.AlignTop)
        grid.addLayout(self.__initContent__())
        grid.addLayout(self.__initTail__(), Qt.AlignBottom)

    def __initHead__(self):
        self._searchEdit = LineEdit(iconUrl=getResourcePath() +
                                    "/svg/search2.svg")
        self._searchErrLabel = Label('', LabelStyle.SearchErr)
        self._searchErrLabel.hide()
        layout = QVBoxLayout()
        layout.addWidget(self._searchEdit)
        layout.addWidget(self._searchErrLabel)
        layout.setContentsMargins(0, 0, 0, 5)
        return layout

    def __initTail__(self):
        self._trackQualityComboBox = ComboBox([], 150)
        self._videoQualityComboBox = ComboBox([], 150)

        self._prePageBtn = PushButton('', ButtonStyle.PrePage)
        self._nextPageBtn = PushButton('', ButtonStyle.NextPage)

        self._pageIndexEdit = LineEdit('')
        self._pageIndexEdit.setAlignment(Qt.AlignCenter)
        self._pageIndexEdit.setEnabled(False)

        self._downloadBtn = PushButton('Download', ButtonStyle.Primary)

        layout = QHBoxLayout()
        layout.addWidget(Label('Track:'))
        layout.addWidget(self._trackQualityComboBox)
        layout.addWidget(Label('Video:'))
        layout.addWidget(self._videoQualityComboBox)
        layout.addStretch(1)
        layout.addWidget(self._prePageBtn)
        layout.addWidget(self._pageIndexEdit)
        layout.addWidget(self._nextPageBtn)
        layout.addWidget(self._downloadBtn)
        return layout

    def __initContent__(self):
        self._tabWidget = QTabWidget(self)
        self._tabWidget.addTab(self.__initTable__(Type.Album), "ALBUM")
        self._tabWidget.addTab(self.__initTable__(Type.Track), "TRACK")
        self._tabWidget.addTab(self.__initTable__(Type.Video), "VIDEO")
        self._tabWidget.addTab(self.__initTable__(Type.Playlist), "PLAYLIST")

        layout = QVBoxLayout()
        layout.addWidget(self._tabWidget)
        return layout

    def __initTable__(self, stype: Type):
        columnHeads = []
        columnWidths = []
        if stype == Type.Album:
            columnHeads = [
                '#', ' ', ' ', 'Title', 'Artists', 'Release', 'Duration'
            ]
            columnWidths = [50, 60, 60, 400, 200, 200]
        elif stype == Type.Track:
            columnHeads = ['#', ' ', 'Title', 'Album', 'Artists', 'Duration']
            columnWidths = [50, 60, 400, 200, 200]
        elif stype == Type.Video:
            columnHeads = ['#', ' ', ' ', 'Title', 'Artists', 'Duration']
            columnWidths = [50, 60, 60, 400, 200, 200]
        elif stype == Type.Playlist:
            columnHeads = ['#', ' ', 'Title', 'Artist', 'Duration']
            columnWidths = [50, 60, 400, 200, 200]

        self._table[stype] = TableWidget(columnHeads, self._rowCount)
        for index, width in enumerate(columnWidths):
            self._table[stype].setColumnWidth(index, width)

        return self._table[stype]

    def __clearTableRowItems__(self, stype: Type, fromIndex: int):
        endIndex = self._rowCount - 1
        columnNum = self._table[stype].columnCount()
        while fromIndex <= endIndex:
            for colIdx in range(0, columnNum):
                self._table[stype].addItem(fromIndex, colIdx, '')
            fromIndex += 1

    def setTableItems(self, stype: Type, indexOffset: int,
                      result: tidal_dl.model.SearchResult):
        if stype == Type.Album:
            items = result.albums.items
            datas = []
            for index, item in enumerate(items):
                rowData = [
                    str(index + 1 + indexOffset),
                    QUrl(API.getCoverUrl(item.cover)),
                    API.getFlag(item, Type.Album, True), item.title,
                    item.artists[0].name,
                    str(item.releaseDate),
                    getDurationString(item.duration)
                ]
                datas.append(rowData)

        elif stype == Type.Track:
            items = result.tracks.items
            datas = []
            for index, item in enumerate(items):
                rowData = [
                    str(index + 1 + indexOffset),
                    API.getFlag(item, Type.Track, True), item.title,
                    item.album.title, item.artists[0].name,
                    getDurationString(item.duration)
                ]
                datas.append(rowData)

        elif stype == Type.Video:
            items = result.videos.items
            datas = []
            for index, item in enumerate(items):
                rowData = [
                    str(index + 1 + indexOffset),
                    QUrl(API.getCoverUrl(item.imageID)),
                    API.getFlag(item, Type.Video, True), item.title,
                    item.artists[0].name,
                    getDurationString(item.duration)
                ]
                datas.append(rowData)

        elif stype == Type.Playlist:
            items = result.playlists.items
            datas = []
            for index, item in enumerate(items):
                rowData = [
                    str(index + 1 + indexOffset),
                    QUrl(API.getCoverUrl(item.squareImage)), item.title, '',
                    getDurationString(item.duration)
                ]
                datas.append(rowData)

        for index, rowData in enumerate(datas):
            for colIdx, obj in enumerate(rowData):
                self._table[stype].addItem(index, colIdx, obj)

        self.__clearTableRowItems__(stype, len(items))
        self._table[stype].viewport().update()

    def getSearchText(self):
        return self._searchEdit.text()

    def setSearchErrmsg(self, text: str):
        self._searchErrLabel.setText(text)
        if text != '':
            self._searchErrLabel.show()
        else:
            self._searchErrLabel.hide()

    def setPageIndex(self, index, sum):
        self._pageIndexEdit.setText(str(index) + '/' + str(sum))

    def getPageIndex(self) -> (int, int):
        nums = self._pageIndexEdit.text().split('/')
        return int(nums[0]), int(nums[1])

    def getSelectedTabIndex(self):
        return self._tabWidget.currentIndex()

    def getSelectedTableIndex(self, stype: Type):
        array = self._table[stype].selectedIndexes()
        if len(array) <= 0:
            return -1
        return array[0].row()

    def setTrackQualityItems(self, items: list, curItem=None):
        self._trackQualityComboBox.setItems(items)
        if curItem is not None:
            self._trackQualityComboBox.setCurrentText(curItem)

    def setVideoQualityItems(self, items: list, curItem=None):
        self._videoQualityComboBox.setItems(items)
        if curItem is not None:
            self._videoQualityComboBox.setCurrentText(curItem)

    def getTrackQualityText(self):
        return self._trackQualityComboBox.currentText()

    def getVideoQualityText(self):
        return self._videoQualityComboBox.currentText()

    def connectButton(self, name: str, func):
        if name == 'search':
            self._searchEdit.returnPressed.connect(func)
        elif name == 'prePage':
            self._prePageBtn.clicked.connect(func)
        elif name == 'nextPage':
            self._nextPageBtn.clicked.connect(func)
        elif name == 'download':
            self._downloadBtn.clicked.connect(func)

    def connectTab(self, func):
        self._tabWidget.currentChanged.connect(func)

    def connectQualityComboBox(self, name: str, func):
        if name == 'track':
            self._trackQualityComboBox.currentIndexChanged.connect(func)
        else:
            self._videoQualityComboBox.currentIndexChanged.connect(func)
예제 #33
0
class ShowTest(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        try:
            self.info = []
            self.data = loads(crypt(open('test.UT', encoding='UTF-16').read()))
            self.tab = QTabWidget()
            self.setCentralWidget(self.tab)
            self.set_tab()

            self.end_btn = QPushButton('Завершить работу', self)
            self.end_btn.clicked.connect(self.finish_test)

            self.tab.addTab(self.end_btn, 'Завершить работу')
        except Exception as e:
            print(e)

    def set_tab(self):
        for i in range(len(self.data)):
            self.info.append({})
            self.info[i]['page'] = QuestPage()

            self.info[i]['page'].back_btn.clicked.connect(self.switch)
            self.info[i]['page'].fwd_btn.clicked.connect(self.switch)

            self.info[i]['page'].question.setPlainText(
                self.data[i]['question'])

            n = len(self.data[i]['vars'])
            if self.data[i]['type'] == 0:
                self.info[i]['btns'] = []
                for j in range(n):
                    hbox = QHBoxLayout()
                    rb = QRadioButton()
                    self.info[i]['btns'].append(rb)
                    hbox.addWidget(rb)
                    label = QLabel(self.data[i]['vars'][j])
                    hbox.addWidget(label)
                    hbox.addStretch()
                    if j == n - 1 and j % 2 == 0:
                        self.info[i]['page'].verticalLayout_1.addLayout(hbox)
                    else:
                        if j % 2 == 0:
                            self.info[i]['page'].verticalLayout_2.addLayout(
                                hbox)
                        else:
                            self.info[i]['page'].verticalLayout_3.addLayout(
                                hbox)
            elif self.data[i]['type'] == 1:
                self.info[i]['btns'] = []
                for j in range(n):
                    hbox = QHBoxLayout()
                    chb = QCheckBox()
                    self.info[i]['btns'].append(chb)
                    hbox.addWidget(chb)
                    label = QLabel(self.data[i]['vars'][j])
                    hbox.addWidget(label)
                    hbox.addStretch()
                    if j == n - 1 and j % 2 == 0:
                        self.info[i]['page'].verticalLayout_1.addLayout(hbox)
                    else:
                        if j % 2 == 0:
                            self.info[i]['page'].verticalLayout_2.addLayout(
                                hbox)
                        else:
                            self.info[i]['page'].verticalLayout_3.addLayout(
                                hbox)
            else:
                self.info[i]['page'].verticalLayout_1.addWidget(QLineEdit())

            self.tab.addTab(self.info[i]['page'], str(i + 1))

    def switch(self):
        if self.sender().text() == 'Назад':
            self.tab.setCurrentIndex(self.tab.currentIndex() - 1)
        else:
            self.tab.setCurrentIndex(self.tab.currentIndex() + 1)

    def finish_test(self):
        try:
            for i in range(len(self.info)):
                if self.data[i]['type'] == 0:
                    for j in self.info[i]['btns']:
                        if self.info[i]['btns'][j].isChecked:
                            if j == int(self.data[i]['rightAnswers']):
                                print('OK')
                            else:
                                print('F**K YOU')
        except Exception as e:
            print(e)
예제 #34
0
class ImportData(QWidget):
    def __init__(self, parent, name):
        font = config.font
        super(QWidget, self).__init__(parent, Qt.Window)

        self.setWindowTitle('Import')
        self.setFixedSize(850, 512)
        self.move(0, 50)

        self.tabs = QTabWidget(self)
        self.label1 = QLabel(self)
        self.label2 = QLabel(self)
        self.label1.resize(600, 512)
        self.label2.resize(600, 512)
        self.tabs.resize(600, 512)
        self.tabs.addTab(self.label1, "Normal")
        self.tabs.addTab(self.label2, "Polar")

        self.textbox = QLineEdit(self)
        self.textbox.setText("-90")
        self.textbox.resize(31, 22)
        self.textbox.move(640, 20)
        self.textbox.setFont(QFont(font, 12))
        self.textbox.setMaxLength(3)

        self.data = AnalyzeData(self, name)

        btnsave = QPushButton('Save', self)
        btnsave.resize(93, 28)
        btnsave.move(740, 470)
        btnsave.setFont(QFont(font, 12))
        btnsave.clicked.connect(self.save_analyze)

        btn = QPushButton('Analyze', self)
        btn.resize(93, 28)
        btn.move(620, 470)
        btn.setFont(QFont(font, 12))
        btn.clicked.connect(self.analyze_button_clicked)

        self.interpolation = QCheckBox("Use interpolation", self)
        self.interpolation.resize(121, 20)
        self.interpolation.move(690, 20)
        self.interpolation.setFont(QFont(font, 10))

        phi = QLabel('φ :', self)
        phi.resize(31, 21)
        phi.move(610, 20)
        phi.setFont(QFont(font, 12))

        degrees = QLabel('°', self)
        degrees.resize(16, 16)
        degrees.move(672, 20)
        degrees.setFont(QFont(font, 12))

        self.direction = QLabel('', self)
        self.direction.resize(61, 21)
        self.direction.move(690, 50)
        self.direction.setFont(QFont(font, 12))

        max_direction = QLabel("Direction :", self)
        max_direction.resize(81, 21)
        max_direction.move(610, 50)
        max_direction.setFont(QFont(font, 12))

        zero = QLabel("Zeros :", self)
        zero.setFont(QFont(font, 12))
        zero.resize(55, 16)
        zero.move(610, 110)

        self.zero = QListWidget(self)
        self.zero.setFont(QFont(font, 12))
        self.zero.resize(91, 81)
        self.zero.move(670, 80)

        self.main_length = QLabel('', self)
        self.main_length.setFont(QFont(font, 12))
        self.main_length.resize(51, 16)
        self.main_length.move(640, 170)

        theta = QLabel('θ₀ :', self)
        theta.setFont(QFont(font, 14))
        theta.move(610, 170)
        theta.resize(31, 16)

        theta3dB = QLabel('θ₀̣₅:', self)
        theta3dB.setFont(QFont(font, 14))
        theta3dB.move(610, 200)
        theta3dB.resize(31, 16)

        self.main_length_3dB = QLabel('', self)
        self.main_length_3dB.setFont(QFont(font, 12))
        self.main_length_3dB.move(640, 200)
        self.main_length_3dB.resize(51, 16)

    def analyze_button_clicked(self):
        self.zero.clear()
        phi = int(self.textbox.text())
        phi = phi - (phi % 5)
        if phi > 90:
            phi = 90
        if phi < -90:
            phi = -90
        self.textbox.setText(str(phi))
        if self.interpolation.checkState():
            self.data.delta = 1
        else:
            self.data.delta = 0
        self.data.analyze(phi)
        for phi in self.data.get_zeros():
            self.zero.addItem(phi)
        self.data.show('cache/tmp/normal.png', 0)
        self.data.show('cache/tmp/polar.png', 1)
        pixmap1 = QPixmap('cache/tmp/normal.png')
        pixmap2 = QPixmap('cache/tmp/polar.png')
        self.label1.setPixmap(pixmap1)
        self.label2.setPixmap(pixmap2)
        self.main_length.setText(str(self.data.get_length()) + "°")
        self.main_length_3dB.setText(str(self.data.get_length_3dB()) + "°")
        self.direction.setText(
            str(int(self.data.get_direction_of_maximum()[0])) + "°")

    def closeEvent(self, event):
        if config.system == "Windows":
            system('del cache/tmp/normal.png')
            system('del cache/tmp/polar.png')
        elif config.system == "Linux":
            system('rm cache/tmp/normal.png')
            system('rm cache/tmp/polar.png')

    def save_analyze(self):
        print(Path('cache/tmp/normal.png'))
        if self.tabs.currentIndex():
            fileName, _ = QFileDialog.getSaveFileName(
                self, '', "polar(" + self.textbox.text() + ").png", '*.png')
            if fileName:
                copyfile(Path('cache/tmp/polar.png'), fileName)
        else:
            fileName, _ = QFileDialog.getSaveFileName(
                self, '', "normal(" + self.textbox.text() + ").png", '*.png')
            if fileName:
                copyfile(Path('cache/tmp/normal.png'), fileName)
예제 #35
0
class StudentGroupsTabs(QWidget):
    def __init__(self, parent, student_listings=None):
        super().__init__(parent)
        if student_listings is None:
            self.student_listings = students.StudentListings()
            inserted_group = students.StudentGroup(0, 'INSERTED')
            self.student_listings.create_listing(inserted_group)
        else:
            self.student_listings = student_listings
        layout = QVBoxLayout(self)
        self.setLayout(layout)
        self.tabs = QTabWidget(self)
        # Special tab for creating a new group:
        self.tabs.addTab(QWidget(), '  +  ')
        # Group 0 is special: don't show it
        for listing in self.student_listings[1:]:
            self._add_group_tab(listing)
        # At least one normal group needs to be present:
        if len(self.student_listings) == 1:
            self._create_default_group()
        button_load = QPushButton(_('Add students from file'), parent=self)
        button_new_student = QPushButton(
            QIcon(utils.resource_path('new_id.svg')),
            _('New student'),
            parent=self)
        button_remove = QPushButton(
            QIcon(utils.resource_path('discard.svg')),
            _('Remove group'),
            parent=self)
        layout.addWidget(self.tabs)
        layout.addWidget(button_load)
        layout.addWidget(button_new_student)
        layout.addWidget(button_remove)
        layout.setAlignment(button_load, Qt.AlignHCenter)
        layout.setAlignment(button_new_student, Qt.AlignHCenter)
        layout.setAlignment(button_remove, Qt.AlignHCenter)
        self.tabs.setCurrentIndex(0)
        self._active_tab = 0
        self.tabs.currentChanged.connect(self._tab_changed)
        self.tabs.tabBarDoubleClicked.connect(self._rename_group)
        button_load.clicked.connect(self._load_students)
        button_new_student.clicked.connect(self._new_student)
        button_remove.clicked.connect(self._remove_group)

    def _load_students(self):
        index = self.tabs.currentIndex()
        file_name, __ = QFileDialog.getOpenFileName(
            self,
            _('Select the student list file'),
            '',
            FileNameFilters.student_list,
            None,
            QFileDialog.DontUseNativeDialog)
        try:
            if file_name:
                with students.StudentReader.create(file_name) as reader:
                    student_list = list(reader.students())
                # Flag duplicate student ids:
                warn_duplicates = False
                for s in self.student_listings.find_duplicates(student_list):
                    s.is_duplicate = True
                    warn_duplicates = True
                if warn_duplicates:
                    QMessageBox.warning(
                        self,
                        _('Importing a student list'),
                        _('Some student ids are already in the list. '
                          'Remove them or cancel the import operation.'))
                column_map = reader.column_map.normalize()
                preview_dialog = DialogPreviewStudents(
                    self, student_list, column_map)
                result = preview_dialog.exec_()
                if result == QMessageBox.Accepted:
                    self.tabs.widget(index).add_students(student_list)
        except Exception as e:
            QMessageBox.critical(
                self,
                _('Error in student list'),
                file_name + '\n\n' + str(e))

    def _new_student(self):
        index = self.tabs.currentIndex()
        dialog = NewStudentDialog(
            self.student_listings,
            group_index=index,
            parent=self)
        student = dialog.exec_()
        if student is not None:
            self.tabs.widget(index).listing_updated()

    def _remove_group(self):
        index = self.tabs.currentIndex()
        if len(self.student_listings[index + 1]) > 0:
            result = QMessageBox.warning(
                self,
                _('Warning'),
                _('This group and its students will be removed. '
                  'Are you sure you want to continue?'),
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No)
            remove = (result == QMessageBox.Yes)
        else:
            remove = True
        if remove:
            try:
                self.student_listings.remove_at(index + 1)
                if len(self.student_listings) > 1:
                    if index == self.tabs.count() - 2:
                        self.tabs.setCurrentIndex(index - 1)
                    else:
                        self.tabs.setCurrentIndex(index + 1)
                else:
                    self._create_default_group()
                    self.tabs.setCurrentIndex(1)
                self.tabs.removeTab(index)
            except students.CantRemoveGroupException:
                QMessageBox.critical(
                    self,
                    _('Error'),
                    _('This group cannot be removed because '
                      'exams have been graded for some of its students.'))

    def _add_group_tab(self, listing, show=False):
        self.tabs.insertTab(
            self.tabs.count() - 1,
            GroupWidget(listing, self),
            listing.group.name
        )
        if show:
            self.tabs.setCurrentIndex(self.tabs.count() - 2)

    def _new_group(self):
        group_name = GroupNameDialog(parent=self).exec_()
        if group_name is not None:
            group = students.StudentGroup(None, group_name)
            listing = self.student_listings.create_listing(group)
            self._add_group_tab(listing, show=True)
        else:
            self.tabs.setCurrentIndex(self._active_tab)

    def _create_default_group(self):
        group = students.StudentGroup(None, _('Students'))
        listing = self.student_listings.create_listing(group)
        self._add_group_tab(listing, show=True)

    def _rename_group(self, index):
        name = self.student_listings[index + 1].group.name
        new_name = GroupNameDialog(group_name=name, parent=self).exec_()
        if new_name is not None and new_name != name:
            self.student_listings[index + 1].rename(new_name)
            self.tabs.setTabText(index, new_name)

    def _tab_changed(self, index):
        if index == self.tabs.count() - 1:
            # The last (special) tab has been activated: create a new group
            self._new_group()
        self._active_tab = self.tabs.currentIndex()
예제 #36
0
class MainWindow(QDialog, window1.Ui_PyDialog):
    def __init__(self, parent=None):
        global arguments, return_keyword
        self.event_entered = False
        self.event2_entered = False
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        
        if arguments.stayontop:
            from PyQt5.QtCore import Qt
            self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.label.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding))

        self.button_ids = ["details_button", "ok_button", "yes_button", "no_button", "continue_button", "save_button", "cancel_button"]
        self.button_names = {
            "details_button":_("Details"), 
            "ok_button":_("Ok"), 
            "yes_button":_("Yes"), 
            "no_button":_("No"), 
            "continue_button":_("Continue"),
            "save_button":_("Save"),
            "cancel_button":_("Cancel")
        }
        
        self.button_values = {}
        self.create_elements()
        self.word_wrap()

    def word_wrap(self):
        if self.label.sizeHint().width() > 600:
            self.label.setWordWrap(True)
            self.label.setScaledContents(True)
            self.label.setMinimumWidth(600)

    def create_elements(self):
        self.active_buttons = dict((e, False) for e in self.button_names)
        self.progressbar_cancelled = False

        self.hide_unused_elements()
        self.init_conf()
        self.create_buttons()
        self.set_button_labels()

        noab = len(list(filter(lambda x: self.active_buttons[x], self.active_buttons)))
        self.reject_value = noab - 1

        
    def hide_unused_elements(self):
        """ Hide the unused elements """
        global arguments
        if not arguments.forkedprogressbar:
            self.progressBar.hide()
        if not arguments.slider:
            self.horizontalSlider.hide()
        if not arguments.combobox:
            self.comboBox.hide()
        if not arguments.inputbox and not arguments.password:
            self.lineEdit.hide()
        if not arguments.combobox and not arguments.password:
            self.label_2.hide()


    def init_conf(self):
        """ Initial configurations (buttons and labels) """
        global arguments
        if arguments.title:
            self.setWindowTitle(arguments.title)
        if arguments.icon:
            from PyQt5.QtGui import QIcon
            icon = QIcon(arguments.icon)
            self.setWindowIcon(icon)

        if arguments.yesno or arguments.warningyesno:
            self.enable_buttons(["yes_button", "no_button"])
            if arguments.yesno:
                self.label.setText(arguments.yesno)
            else:
                self.label.setText(arguments.warningyesno)

        elif arguments.yesnocancel or arguments.warningyesnocancel:
            self.enable_buttons(["yes_button", "no_button", "cancel_button"])
            if arguments.yesnocancel:
                self.label.setText(arguments.yesnocancel)
            else:
                self.label.setText(arguments.warningyesnocancel)

        elif arguments.sorry or arguments.error or arguments.msgbox:
            self.enable_buttons(["ok_button"])
            if arguments.sorry:
                self.label.setText(arguments.sorry)
            elif arguments.error:
                self.label.setText(arguments.error)
            else:
                self.label.setText(arguments.msgbox)

        elif arguments.detailedsorry or arguments.detailederror:
            self.enable_buttons(["details_button", "ok_button"])
            if arguments.detailedsorry:
                self.label.setText(arguments.detailedsorry[0])
                self.details = arguments.detailedsorry[1]
            else:
                self.label.setText(arguments.detailederror[0])
                self.details = arguments.detailederror[1]

        elif arguments.warningcontinuecancel:
            self.enable_buttons(["continue_button", "cancel_button"])
            self.label.setText(arguments.warningcontinuecancel)
        
        elif arguments.forkedprogressbar:
            self.label.setText(arguments.forkedprogressbar[0])
            if len(arguments.forkedprogressbar) > 1:
                self.progressBar.setMaximum(int(arguments.forkedprogressbar[1]))
                
        elif arguments.slider:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.label.setText(arguments.slider[0])
            if len(arguments.slider) > 1:
                self.horizontalSlider.setMinimum(int(arguments.slider[1]))
            if len(arguments.slider) > 2:
                self.horizontalSlider.setMaximum(int(arguments.slider[2]))
            if len(arguments.slider) > 3:
                self.horizontalSlider.setSingleStep(int(arguments.slider[3]))
                self.horizontalSlider.setPageStep(int(arguments.slider[3]))
        
        elif arguments.inputbox:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.label.setText(arguments.inputbox[0])
            if len(arguments.inputbox) > 1:
                self.lineEdit.setText(arguments.inputbox[1])

        elif arguments.password:
            self.enable_buttons(["ok_button", "cancel_button"])
            self.lineEdit.setEchoMode(2)
            self.label.setText(arguments.password[0])
            self.label_2.setText(_("Password:"******"ok_button", "cancel_button"])
            
    def create_scrollarea(self, scrollLayout):
            from PyQt5.QtWidgets import QHBoxLayout, QWidget, QScrollArea
            from PyQt5.QtCore import Qt

            scrollWidget = QWidget()
            scrollAreaLayout = QHBoxLayout()                
            scrollWidget.setLayout(scrollLayout)
            #hscrollbar = QScrollBar()
            #vscrollbar = QScrollBar()
            scrollArea = QScrollArea()
            #scrollArea.setHorizontalScrollBar(hscrollbar)
            #scrollArea.setVerticalScrollBar(vscrollbar)
            #scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            #scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.set_scrollarea_height(scrollArea)
            scrollArea.setWidget(scrollWidget)
            scrollAreaLayout.addWidget(scrollArea)
            #scrollAreaLayout.addWidget(vscrollbar)
            return scrollAreaLayout
            #, hscrollbar
            

    def set_scrollarea_height(self, scrollarea):
        if arguments.checklist:
            elements = (len(arguments.checklist)-1) / 3
        elif arguments.radiolist:
            elements = (len(arguments.radiolist)-1) / 3
        elif arguments.menu:
            elements = (len(arguments.menu)-1) / 2
        if elements < 3:
            pass
        elif elements == 3:
            scrollarea.setMinimumHeight(90)
        elif elements == 4:
            scrollarea.setMinimumHeight(115)
        else:
            scrollarea.setMinimumHeight(140)

    def add_checkboxes(self, tab=False):
        from PyQt5.QtWidgets import QCheckBox, QVBoxLayout
        scrollLayout = QVBoxLayout()
        checkboxes = []
        if tab:
            i = 2
            name = "tab"
        else:
            i = 1
            name = "checklist"
        l = len(arguments.__dict__[name])
        while i < l:
            checkbox = QCheckBox(arguments.__dict__[name][i+1])
            if arguments.__dict__[name][i+2].lower() in ["true", "on"]:
                checkbox.setCheckState(2)
            checkboxes.append({"box":checkbox, "result":arguments.__dict__[name][i]})
            scrollLayout.addWidget(checkbox)
            i += 3
        return scrollLayout, checkboxes
            
    def add_radiobuttons(self, tab=False):
        from PyQt5.QtWidgets import QRadioButton, QButtonGroup, QVBoxLayout
        scrollLayout = QVBoxLayout()
        buttonGroup = QButtonGroup()
        buttongroup_results = {}
        i = 1
        if tab:
            name = "tab"
            i = 2
        elif arguments.radiolist:
            name = "radiolist"
        elif arguments.menu:
            name = "menu"
        arglen = len(arguments.__dict__[name])
        while i < arglen:
            if arguments.radiolist:
                radiobutton = QRadioButton(arguments.__dict__[name][i+1])
                buttongroup_results[radiobutton] = arguments.__dict__[name][i]
                if arguments.__dict__[name][i+2].lower() in ["true", "on"]:
                    radiobutton.setChecked(True)
                i += 3
            else:
                radiobutton = QRadioButton(arguments.__dict__[name][i+1])
                buttongroup_results[radiobutton] = arguments.__dict__[name][i]
                if i == 1:
                    radiobutton.setChecked(True)
                i += 2
            scrollLayout.addWidget(radiobutton)
            buttonGroup.addButton(radiobutton)
        return scrollLayout, buttonGroup, buttongroup_results

    def set_button_labels(self):
        """Set the button labels"""
        global arguments
        if arguments.yeslabel and self.active_buttons["yes_button"]:
            self.buttons["yes_button"].setText(arguments.yeslabel)
        if arguments.nolabel and self.active_buttons["no_button"]:
            self.buttons["no_button"].setText(arguments.nolabel)
        if arguments.cancellabel and self.active_buttons["cancel_button"]:
            self.buttons["cancel_button"].setText(arguments.cancellabel)
        if arguments.continuelabel and self.active_buttons["continue_button"]:
            self.buttons["continue_button"].setText(arguments.continuelabel)


    def create_buttons(self):
        global arguments
        self.buttons = {}
        
        i = 0
        for button_id in self.button_ids:
            if self.active_buttons[button_id]:
                self.buttons[button_id] = QPushButton(self.button_names[button_id])
                self.horizontalLayout.addWidget(self.buttons[button_id])
                if button_id == "details_button":
                    self.buttons["details_button"].clicked.connect(self.details_button_clicked)
                elif button_id == "cancel_button":
                    self.buttons[button_id].clicked.connect(self.reject)
                else:
                    self.button_values[button_id] = i
                    exec("self.buttons[button_id].clicked.connect(self."+button_id+"_clicked)")
                    i += 1
    
    
    def print_checkboxes(self):
        if arguments.separateoutput:
            fs = '{}'
            data_end = "\n"
        else:
            fs = '"{}"'
            data_end = " "
        for e in self.checkboxes:
            if e["box"].isChecked():
                print(fs.format(e["result"]), end=data_end)
        if arguments.tab:
            for e in self.checkboxes2:
                if e["box"].isChecked():
                    print(fs.format(e["result"]), end=data_end)
                    
    def get_checked_radiobutton(self):
        n = ""
        if arguments.tab:
             if self.tabwidget.currentIndex() == 1:
                 n = "2"
        radiobutton_name = self.__dict__["buttonGroup"+n].checkedButton()
        print(self.__dict__["buttongroup_results"+n][radiobutton_name])
    

    def ok_button_clicked(self):
        if arguments.slider:
            print(self.horizontalSlider.value())
        elif arguments.inputbox or arguments.password:
            print(self.lineEdit.text())
        elif arguments.checklist:
            self.print_checkboxes()
        elif arguments.radiolist or arguments.menu:
            self.get_checked_radiobutton()
        print(return_keyword+str(self.button_values["ok_button"])+">")
        self.done(0)
    
    def yes_button_clicked(self):
        print(return_keyword+str(self.button_values["yes_button"])+">")
        self.done(0)
    
    def no_button_clicked(self):
        print(return_keyword+str(self.button_values["no_button"])+">")
        self.done(0)
    
    def continue_button_clicked(self):
        print(return_keyword+str(self.button_values["continue_button"])+">")
        self.done(0)

    def save_button_clicked(self):
        print(return_keyword+str(self.button_values["save_button"])+">")
        self.done(0)
    
    def reject(self):
        print(return_keyword+str(self.reject_value)+">")
        self.done(0)

    def enable_buttons (self, button_list):
        for button in button_list:
            self.active_buttons[button] = True
            
    def details_button_clicked (self):
        self.label.setText(self.label.text() + '\n\n' + self.details)
        self.buttons["details_button"].setDisabled(True)

    def progressbar_cancel_clicked(self):
        self.progressbar_cancelled = True

    def showCancelButton(self):
        if not "cancel_button" in self.buttons:
            self.buttons["cancel_button"] = QPushButton(self.button_names["cancel_button"])
            self.buttons["cancel_button"].clicked.connect(self.progressbar_cancel_clicked)
            self.horizontalLayout.addWidget(self.buttons["cancel_button"])
            self.progressbar_cancelled = False
        self.buttons["cancel_button"].show()
예제 #37
0
class AnalyzerWidget(QWidget):
    def __init__(self):
        super().__init__()
        hbox = QHBoxLayout()

        # -----------------------------
        # Create frames
        # -----------------------------

        # 1. Plot frame:
        plotFrame = QFrame()
        plotFrame.setFrameShape(QFrame.Panel | QFrame.Raised)
        plotFrame.setStyleSheet(stylesheet_qframe1())
        figure = plt.figure()
        canvas = FigureCanvas(figure)
        ln = 100000
        data = [random.random() for i in range(ln)]
        data = np.cumsum(data - np.mean(data))
        ax = figure.add_subplot(111)
        plt.subplots_adjust(left=0.00,
                            bottom=0.002,
                            right=1,
                            top=1,
                            wspace=0,
                            hspace=0)
        ax.plot(data)
        ax.grid()
        ax.set_facecolor('#C4C4C4')
        ax.grid(color='#B80C09', linestyle=':')
        plt.xlim([0, len(data)])
        canvas.draw()
        pLayout = QVBoxLayout()
        pLayout.addWidget(canvas)
        plotFrame.setLayout(pLayout)
        plotFrame.setContentsMargins(0, 0, 0, 0)

        # 2. Horizontal sliders frame:
        sHbox = QVBoxLayout()
        slider1h = QSlider(Qt.Horizontal, self)
        slider1h.setStyleSheet(stylesheet_h())
        slider2h = QSlider(Qt.Horizontal, self)
        slider2h.setStyleSheet(stylesheet_h())
        sHbox.addWidget(slider1h)
        sHbox.addWidget(slider2h)
        sHbox.setSpacing(0)
        sHbox.setContentsMargins(1, 0, 1, 0)
        sFrameH = QFrame()
        sFrameH.setFrameShape(QFrame.Panel | QFrame.Raised)
        sFrameH.setLayout(sHbox)

        # 3. Vertical sliders frame:
        sVbox = QHBoxLayout()
        slider1v = QSlider(Qt.Vertical, self)
        slider1v.setStyleSheet(stylesheet_v())
        slider2v = QSlider(Qt.Vertical, self)
        slider2v.setStyleSheet(stylesheet_v())
        sVbox.addWidget(slider1v)
        sVbox.addWidget(slider2v)
        sVbox.setSpacing(0)
        sVbox.setContentsMargins(1, 0, 1, 0)
        sFrameV = QFrame()
        sFrameV.setFrameShape(QFrame.Panel | QFrame.Raised)
        sFrameV.setLayout(sVbox)

        # 4. SlidersControl frame:
        cornerFrame = QFrame()
        btnMax1 = QPushButton('max', cornerFrame)
        btnMax2 = QPushButton('max', cornerFrame)
        btnMax1.setGeometry(1, 0, 30, 20)
        btnMax2.setGeometry(1, 17, 30, 20)
        editMax1 = QLineEdit('0', cornerFrame)
        editMax2 = QLineEdit('0', cornerFrame)
        editMax1.setGeometry(31, 0, 60, 20)
        editMax2.setGeometry(31, 17, 60, 20)
        cornerFrame.setFrameShape(QFrame.Panel | QFrame.Raised)

        # 5. Control Panel frame:
        controlFrame = QFrame()
        controlFrame.setFrameShape(QFrame.Panel | QFrame.Raised)
        controlFrame.setLineWidth(2)
        control_tab = QTabWidget()
        cTab1 = QWidget()

        # Tab Browser
        # ------------------------
        cLayout1 = QVBoxLayout()
        cFrame1 = QFrame()
        self.lst_file = QListWidget()
        self.lst_dir = QListWidget()
        self.tab_files = QTabWidget()
        self.tab_files.addTab(self.lst_file, 'Files')
        self.tab_files.addTab(self.lst_dir, 'Directories')
        cLayout_btn = QHBoxLayout()
        self.btn_load = QPushButton('Load')
        self.btn_load.setObjectName('Load')
        self.btn_load.clicked.connect(self.openFileNameDialog)
        self.btn_info = QPushButton('Info')
        self.btn_info.setObjectName('Info')
        self.btn_info.clicked.connect(self.openFileNameDialog)
        self.btn_prev = QPushButton('Preview')
        self.btn_prev.setObjectName('Preview')
        self.btn_prev.clicked.connect(self.openFileNameDialog)

        # get open histories
        self.filepath = ''
        if os.path.exists('files_history.txt'):
            with open('files_history.txt', 'r') as f:
                files_history = f.read().splitlines()
            path_history = getPathList(files_history)
            self.filepath = path_history[0]
        else:
            files_history = list()
            path_history = list()
        for item in files_history:
            self.lst_file.addItem(item)
        for item in path_history:
            self.lst_dir.addItem(item)

        cLayout_btn.addWidget(self.btn_load)
        cLayout_btn.addWidget(self.btn_info)
        cLayout_btn.addWidget(self.btn_prev)
        lbl_hist = QLabel('Load data files history')
        cLayout1.addWidget(lbl_hist)
        cLayout1.addWidget(self.tab_files)
        cLayout1.addLayout(cLayout_btn)
        cFrame1.setLayout(cLayout1)

        lbl_obj = QLabel('Loaded objects')
        b_tree = QTreeView()
        b_tree.setAlternatingRowColors(True)
        b_tree_model = QStandardItemModel(0, 5)
        b_tree_node = b_tree_model.invisibleRootItem()
        branch1 = QStandardItem("a")
        branch1.appendRow([QStandardItem("Child A"), None])
        childNode = QStandardItem("Child B")
        branch1.appendRow([childNode, None])
        branch2 = QStandardItem("b")
        branch2.appendRow([QStandardItem("Child C"), None])
        branch2.appendRow([QStandardItem("Child D"), None])
        branch3 = QStandardItem('c')
        branch4 = QStandardItem('d')

        b_tree_node.appendRow([branch1, None])
        b_tree_node.appendRow([branch2, None])
        b_tree_node.appendRow([branch3, None])
        b_tree_node.appendRow([branch4, None])

        b_tree.setModel(b_tree_model)
        b_tree_model.setHeaderData(0, Qt.Horizontal, 'Name')
        b_tree_model.setHeaderData(1, Qt.Horizontal, 'Type')
        b_tree_model.setHeaderData(2, Qt.Horizontal, 'Data')
        b_tree_model.setHeaderData(3, Qt.Horizontal, 'Size')
        b_tree_model.setHeaderData(4, Qt.Horizontal, 'Modified')
        b_tree.setColumnWidth(0, 70)

        cLayout2 = QVBoxLayout()
        cLayout2.addWidget(lbl_obj)
        cLayout2.addWidget(b_tree)
        cFrame2 = QFrame()
        cFrame2.setLayout(cLayout2)

        cSplitBrowser = QSplitter(Qt.Vertical)

        cSplitBrowser.addWidget(cFrame1)
        cSplitBrowser.addWidget(cFrame2)
        cSplitBrowser.setSizes([200, 50])

        cLayout = QVBoxLayout()
        cLayout.addWidget(cSplitBrowser)
        cLayout.setContentsMargins(0, 0, 0, 0)

        # cLayout.addWidget(cFrame2)
        cFrame = QFrame()
        cFrame.setLayout(cLayout)
        control_tab.addTab(cFrame, 'Browser')

        # Tab Work
        # -------------------------------
        wFrame1 = QFrame()
        wLayout = QGridLayout()
        wLbl_proc = QLabel('Process type')
        wComboBox1 = QComboBox()
        w_list = [
            "Signal view", "Differentiation", "Integration", "Correlation",
            "Allan variance", "Fitting", "Termo compensations", "Calibration",
            "Navigation", "Fourier transform"
        ]
        wComboBox1.setStyleSheet(stylesheet_combo2())
        wComboBox1.addItems(w_list)

        wFrame2 = QFrame()
        wFrame2.setFrameShape(QFrame.Box)
        wLayout.addWidget(wLbl_proc, 0, 0, 1, 1)
        wLayout.addWidget(wComboBox1, 1, 0, 1, 1)
        wLayout.addWidget(wFrame2, 2, 0, 35, 1)
        # Frame 2
        wLayout2 = QHBoxLayout()
        wLayout2.addWidget(QPushButton('one'))
        wLayout2.addWidget(QPushButton('two'))
        wLayout2.addWidget(QPushButton('three'))
        wLayout2.setAlignment(Qt.AlignTop)
        wLayout2.setSpacing(0)
        wFrame2.setLayout(wLayout2)

        wLayout.setContentsMargins(1, 1, 1, 1)
        wFrame1.setLayout(wLayout)
        control_tab.addTab(wFrame1, 'Work')

        # Tab Model
        # -------------------------------
        cTab3 = QWidget()
        control_tab.addTab(cTab3, 'Model')

        control_layout = QVBoxLayout()
        control_layout.addWidget(control_tab)
        control_layout.setContentsMargins(0, 0, 0, 0)
        controlFrame.setLayout(control_layout)

        # 6. Log panel:
        LogEdit = QTextEdit('>>')

        # -----------------------------
        # Split frames
        # -----------------------------

        # 1.  Plot + Vertical sliders:
        split1 = QSplitter(Qt.Horizontal)
        split1.addWidget(plotFrame)
        split1.addWidget(sFrameV)
        split1.setSizes([680, 20])

        # 2.  Horizontal sliders + SlidersControl:
        split2 = QSplitter(Qt.Horizontal)
        split2.addWidget(sFrameH)
        split2.addWidget(cornerFrame)
        split2.setSizes([700, 40])

        # 3.  1 + 2 :
        ver_split = QSplitter(Qt.Vertical)
        ver_split.addWidget(split1)
        ver_split.addWidget(split2)
        ver_split.setSizes([800, 50])

        # 4.  3 + Control Panel:
        hor_split = QSplitter(Qt.Horizontal)
        hor_split.addWidget(ver_split)
        hor_split.addWidget(controlFrame)
        hor_split.setSizes([700, 200])

        # 5.  4 + Log frame:
        bottom_split = QSplitter(Qt.Vertical)
        bottom_split.addWidget(hor_split)
        bottom_split.addWidget(LogEdit)
        bottom_split.setSizes([700, 0])

        hbox.addWidget(bottom_split)

        self.setLayout(hbox)
        QApplication.setStyle(QStyleFactory.create('cleanlooks'))

    def openFileNameDialog(self):
        # Get adress from tab lists:
        if self.tab_files.tabText(self.tab_files.currentIndex()) == 'Files':
            if self.lst_file.currentItem():
                fileName = self.lst_file.currentItem().text()
            else:
                fileName = self.filepath
        elif self.tab_files.tabText(
                self.tab_files.currentIndex()) == 'Directories':
            if self.lst_dir.currentItem():
                fileName = self.lst_dir.currentItem().text()
            else:
                fileName = self.filepath
        # Check adress and set default dir if it not exist
        if not os.path.isfile(fileName) and not os.path.isdir(fileName):
            fileName = self.filepath
        # Load file
        if os.path.isdir(fileName):
            fileName, _ = QFileDialog.getOpenFileName(self,
                                                      "Select file for load",
                                                      directory=fileName)

        print(fileName)
        # Get and sort history, refresh tab lists:
        if os.path.isfile(fileName):
            # create files_history if it is not exits
            if not os.path.exists('files_history.txt'):
                with open('files_history.txt', 'w') as out:
                    out.write(fileName + '\n')
            else:
                # get all files from history
                with open('files_history.txt', 'r') as f:
                    files_history = f.read().splitlines()
                # check file for exist in history
                if not fileName in files_history:
                    with open('files_history.txt', 'a') as f:
                        f.write(fileName + '\n')
                # sort history list by last open file
                with open('files_history.txt', 'r') as f:
                    files_history = f.read().splitlines()
                del files_history[files_history.index(fileName)]
                files_history.insert(0, fileName)
                with open('files_history.txt', 'w') as f:
                    for line in files_history:
                        f.write("%s\n" % line)
            self.lst_file.clear()
            self.lst_dir.clear()
            for currFilePath in files_history:
                self.lst_file.addItem(currFilePath)
            path_history = getPathList(files_history)
            for curPath in path_history:
                self.lst_dir.addItem(curPath)

            # Processing file:
            # ----------------------------------------------
            current_button = self.sender()
            if current_button.objectName() == "Info":
                try:
                    A = ScanDataFile.scan_file(fileName)
                    ScanDataFile.info(A)
                except:
                    pass
            # # -----------------------------------------------
            if current_button.objectName() == "Preview":
                try:
                    A = LoadDataFile(fileName)
                    if A.file_format['read']:
                        self.wnd = ViewData(A)
                        self.wnd.initUI()
                        self.wnd.show()
                    else:
                        err = QErrorMessage(self)
                        err.showMessage('Unreadable format of the file.')
                except:
                    err = QErrorMessage(self)
                    err.showMessage('Can not read this file.')
예제 #38
0
class RunWidget(QWidget):

    allTabsClosed = pyqtSignal()
    projectExecuted = pyqtSignal(str)
    fileExecuted = pyqtSignal(str)

    def __init__(self):
        QWidget.__init__(self)
        self.__programs = []

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

        connections = (
            {
                "target": "tools_dock",
                "signal_name": "executeFile",
                "slot": self.execute_file
            },
            {
                "target": "tools_dock",
                "signal_name": "executeProject",
                "slot": self.execute_project
            },
            {
                "target": "tools_dock",
                "signal_name": "executeSelection",
                "slot": self.execute_selection
            },
            {
                "target": "tools_dock",
                "signal_name": "stopApplication",
                "slot": self.kill_application
            }
        )
        IDE.register_signals("tools_dock", connections)

        self._tabs = QTabWidget()
        self._tabs.setTabsClosable(True)
        self._tabs.setMovable(True)
        self._tabs.setDocumentMode(True)
        vbox.addWidget(self._tabs)
        # Menu for tab
        self._tabs.tabBar().setContextMenuPolicy(Qt.CustomContextMenu)
        self._tabs.tabBar().customContextMenuRequested.connect(
            self._menu_for_tabbar)
        self._tabs.tabCloseRequested.connect(self.close_tab)

        IDE.register_service("run_widget", self)
        _ToolsDock.register_widget(translations.TR_OUTPUT, self)

    def install(self):
        ninjaide = IDE.get_service("ide")
        ninjaide.goingDown.connect(self._kill_processes)

    def _kill_processes(self):
        """Stop all applications"""
        for program in self.__programs:
            program.kill()

    def kill_application(self):
        """Stop application by current tab index"""
        index = self._tabs.currentIndex()
        if index == -1:
            return
        program = self.__programs[index]
        program.kill()

    def _menu_for_tabbar(self, position):
        menu = QMenu()
        close_action = menu.addAction(translations.TR_CLOSE_TAB)
        close_all_action = menu.addAction(translations.TR_CLOSE_ALL_TABS)
        close_other_action = menu.addAction(translations.TR_CLOSE_OTHER_TABS)

        qaction = menu.exec_(self.mapToGlobal(position))

        if qaction == close_action:
            index = self._tabs.tabBar().tabAt(position)
            self.close_tab(index)
        elif qaction == close_all_action:
            self.close_all_tabs()
        elif qaction == close_other_action:
            self.close_all_tabs_except_this()

    def close_tab(self, tab_index):
        program = self.__programs[tab_index]
        self.__programs.remove(program)
        self._tabs.removeTab(tab_index)
        # Close process and delete OutputWidget
        program.main_process.close()
        program.outputw.deleteLater()
        del program.outputw

        if self._tabs.count() == 0:
            # Hide widget
            tools = IDE.get_service("tools_dock")
            tools.hide_widget(self)

    def close_all_tabs(self):
        for _ in range(self._tabs.count()):
            self.close_tab(0)

    def close_all_tabs_except_this(self):
        self._tabs.tabBar().moveTab(self._tabs.currentIndex(), 0)
        for _ in range(self._tabs.count()):
            if self._tabs.count() > 1:
                self.close_tab(1)

    def execute_file(self):
        """Execute the current file"""
        main_container = IDE.get_service("main_container")
        editor_widget = main_container.get_current_editor()
        if editor_widget is not None and (editor_widget.is_modified or
                                          editor_widget.file_path):
            main_container.save_file(editor_widget)
            file_path = editor_widget.file_path
            if file_path is None:
                return
            # Emit signal for plugin!
            self.fileExecuted.emit(editor_widget.file_path)
            extension = file_manager.get_file_extension(file_path)
            # TODO: Remove the IF statment and use Handlers
            if extension == "py":
                self.start_process(filename=file_path)

    def execute_selection(self):
        """Execute selected text or current line if not have a selection"""

        main_container = IDE.get_service("main_container")
        editor_widget = main_container.get_current_editor()
        if editor_widget is not None:
            text = editor_widget.selected_text().splitlines()
            if not text:
                # Execute current line
                text = [editor_widget.line_text()]
            code = []
            for line_text in text:
                # Get part before firs '#'
                code.append(line_text.split("#", 1)[0])
            # Join to execute with python -c command
            final_code = ";".join([line.strip() for line in code if line])
            # Highlight code to be executed
            editor_widget.show_run_cursor()
            # Ok run!
            self.start_process(
                filename=editor_widget.file_path, code=final_code)

    def execute_project(self):
        """Execute the project marked as Main Project."""

        projects_explorer = IDE.get_service("projects_explorer")
        if projects_explorer is None:
            return
        nproject = projects_explorer.current_project
        if nproject:
            main_file = nproject.main_file
            if not main_file:
                # Open project properties to specify the main file
                projects_explorer.current_tree.open_project_properties()
            else:
                # Save project files
                projects_explorer.save_project()
                # Emit a signal for plugin!
                self.projectExecuted.emit(nproject.path)

                main_file = file_manager.create_path(
                    nproject.path, nproject.main_file)
                self.start_process(
                    filename=main_file,
                    python_exec=nproject.python_exec,
                    pre_exec_script=nproject.pre_exec_script,
                    post_exec_script=nproject.post_exec_script,
                    program_params=nproject.program_params
                )

    def start_process(self, **kwargs):
        # First look if we can reuse a tab
        fname = kwargs.get("filename")
        program = None
        for prog in self.__programs:
            if prog.filename == fname:
                if not prog.is_running():
                    program = prog
                    break

        if program is not None:
            index = self.__programs.index(program)
            program.update(**kwargs)
            self._tabs.setCurrentIndex(index)
            program.outputw.gray_out_old_text()
        else:
            program = Program(**kwargs)
            # Create new output widget
            outputw = OutputWidget(self)
            program.set_output_widget(outputw)
            self.add_tab(outputw, program.display_name())
            self.__programs.append(program)

        program.start()

    def add_tab(self, outputw, tab_text):
        inserted_index = self._tabs.addTab(outputw, tab_text)
        self._tabs.setCurrentIndex(inserted_index)
예제 #39
0
class ComboEditor(QWidget):
    def __init__(self, pretty_tab=True, enable_pretty=True):
        QWidget.__init__(self)
        self.setLayout(QVBoxLayout())
        self.layout().setSpacing(0)
        self.layout().setContentsMargins(0, 0, 0, 0)

        self.data = b''
        self.enable_pretty = enable_pretty

        self.tabWidget = QTabWidget()
        self.hexteditor = HextEditor(enable_pretty=self.enable_pretty)
        self.hexeditor = HexEditor()
        self.ppwidg = PrettyPrintWidget()

        self.hexteditor_ind = self.tabWidget.count()
        self.tabWidget.addTab(self.hexteditor, "Text")
        self.hexeditor_ind = self.tabWidget.count()
        self.tabWidget.addTab(self.hexeditor, "Hex")
        self.pp_ind = -1
        if pretty_tab:
            self.pp_ind = self.tabWidget.count()
            self.tabWidget.addTab(self.ppwidg, "Pretty")
        self.tabWidget.currentChanged.connect(self._tab_changed)

        self.previous_tab = self.tabWidget.currentIndex()

        self.layout().addWidget(self.tabWidget)

    @pyqtSlot(int)
    def _tab_changed(self, i):
        # commit data from old tab
        if self.previous_tab == self.hexteditor_ind:
            self.data = self.hexteditor.get_bytes()
        if self.previous_tab == self.hexeditor_ind:
            self.data = self.hexeditor.get_bytes()

        # set up new tab
        if i == self.hexteditor_ind:
            if self.hexteditor.pretty_mode:
                self.hexteditor.set_bytes_highlighted(self.data)
            else:
                self.hexteditor.set_bytes(self.data)
        if i == self.hexeditor_ind:
            self.hexeditor.set_bytes(self.data)
        if i == self.pp_ind:
            self.ppwidg.set_bytes(self.data)
            self.ppwidg.guess_format()

        # update previous tab
        self.previous_tab = self.tabWidget.currentIndex()

    @pyqtSlot(bytes)
    def set_bytes(self, bs):
        self.data = bs
        self.tabWidget.setCurrentIndex(0)
        if self.tabWidget.currentIndex() == self.hexteditor_ind:
            self.hexteditor.set_bytes(bs)
        elif self.tabWidget.currentIndex() == self.hexeditor_ind:
            self.hexeditor.set_bytes(bs)
        elif self.tabWidget.currentIndex() == self.pp_ind:
            self.ppwidg.set_bytes(bs)

    @pyqtSlot(bytes)
    def set_bytes_highlighted(self, bs, lexer=None):
        self.data = bs
        self.tabWidget.setCurrentIndex(0)
        if self.enable_pretty:
            self.hexteditor.set_bytes_highlighted(bs, lexer=lexer)
        else:
            self.set_bytes(bs)

    def get_bytes(self):
        if self.tabWidget.currentIndex() == self.hexteditor_ind:
            self.data = self.hexteditor.get_bytes()
        elif self.tabWidget.currentIndex() == self.hexeditor_ind:
            self.data = self.hexeditor.get_bytes()
        return self.data

    def setReadOnly(self, ro):
        self.hexteditor.setReadOnly(ro)
        self.hexeditor.setReadOnly(ro)
예제 #40
0
class ReTextWindow(QMainWindow):
	def __init__(self, parent=None):
		QMainWindow.__init__(self, parent)
		self.resize(950, 700)
		screenRect = QDesktopWidget().screenGeometry()
		if globalSettings.windowGeometry:
			self.restoreGeometry(globalSettings.windowGeometry)
		else:
			self.move((screenRect.width()-self.width())/2, (screenRect.height()-self.height())/2)
		if not screenRect.contains(self.geometry()):
			self.showMaximized()
		if sys.platform.startswith('darwin'):
			# https://github.com/retext-project/retext/issues/198
			searchPaths = QIcon.themeSearchPaths()
			searchPaths.append('/opt/local/share/icons')
			QIcon.setThemeSearchPaths(searchPaths)
		if globalSettings.iconTheme:
			QIcon.setThemeName(globalSettings.iconTheme)
		if QIcon.themeName() in ('hicolor', ''):
			if not QFile.exists(icon_path + 'document-new.png'):
				QIcon.setThemeName(get_icon_theme())
		if QFile.exists(icon_path+'retext.png'):
			self.setWindowIcon(QIcon(icon_path+'retext.png'))
		elif QFile.exists('/usr/share/pixmaps/retext.png'):
			self.setWindowIcon(QIcon('/usr/share/pixmaps/retext.png'))
		else:
			self.setWindowIcon(QIcon.fromTheme('retext',
				QIcon.fromTheme('accessories-text-editor')))
		self.tabWidget = QTabWidget(self)
		self.initTabWidget()
		self.setCentralWidget(self.tabWidget)
		self.tabWidget.currentChanged.connect(self.changeIndex)
		self.tabWidget.tabCloseRequested.connect(self.closeTab)
		toolBar = QToolBar(self.tr('File toolbar'), self)
		self.addToolBar(Qt.TopToolBarArea, toolBar)
		self.editBar = QToolBar(self.tr('Edit toolbar'), self)
		self.addToolBar(Qt.TopToolBarArea, self.editBar)
		self.searchBar = QToolBar(self.tr('Search toolbar'), self)
		self.addToolBar(Qt.BottomToolBarArea, self.searchBar)
		toolBar.setVisible(not globalSettings.hideToolBar)
		self.editBar.setVisible(not globalSettings.hideToolBar)
		self.actionNew = self.act(self.tr('New'), 'document-new',
			self.createNew, shct=QKeySequence.New)
		self.actionNew.setPriority(QAction.LowPriority)
		self.actionOpen = self.act(self.tr('Open'), 'document-open',
			self.openFile, shct=QKeySequence.Open)
		self.actionOpen.setPriority(QAction.LowPriority)
		self.actionSetEncoding = self.act(self.tr('Set encoding'),
			trig=self.showEncodingDialog)
		self.actionSetEncoding.setEnabled(False)
		self.actionReload = self.act(self.tr('Reload'), 'view-refresh',
			lambda: self.currentTab.readTextFromFile())
		self.actionReload.setEnabled(False)
		self.actionSave = self.act(self.tr('Save'), 'document-save',
			self.saveFile, shct=QKeySequence.Save)
		self.actionSave.setEnabled(False)
		self.actionSave.setPriority(QAction.LowPriority)
		self.actionSaveAs = self.act(self.tr('Save as'), 'document-save-as',
			self.saveFileAs, shct=QKeySequence.SaveAs)
		self.actionNextTab = self.act(self.tr('Next tab'), 'go-next',
			lambda: self.switchTab(1), shct=Qt.CTRL+Qt.Key_PageDown)
		self.actionPrevTab = self.act(self.tr('Previous tab'), 'go-previous',
			lambda: self.switchTab(-1), shct=Qt.CTRL+Qt.Key_PageUp)
		self.actionPrint = self.act(self.tr('Print'), 'document-print',
			self.printFile, shct=QKeySequence.Print)
		self.actionPrint.setPriority(QAction.LowPriority)
		self.actionPrintPreview = self.act(self.tr('Print preview'), 'document-print-preview',
			self.printPreview)
		self.actionViewHtml = self.act(self.tr('View HTML code'), 'text-html', self.viewHtml)
		self.actionChangeEditorFont = self.act(self.tr('Change editor font'),
			trig=self.changeEditorFont)
		self.actionChangePreviewFont = self.act(self.tr('Change preview font'),
			trig=self.changePreviewFont)
		self.actionSearch = self.act(self.tr('Find text'), 'edit-find', shct=QKeySequence.Find)
		self.actionSearch.setCheckable(True)
		self.actionSearch.triggered[bool].connect(self.searchBar.setVisible)
		self.searchBar.visibilityChanged.connect(self.searchBarVisibilityChanged)
		self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E,
			trigbool=self.preview)
		if QIcon.hasThemeIcon('document-preview'):
			self.actionPreview.setIcon(QIcon.fromTheme('document-preview'))
		elif QIcon.hasThemeIcon('preview-file'):
			self.actionPreview.setIcon(QIcon.fromTheme('preview-file'))
		elif QIcon.hasThemeIcon('x-office-document'):
			self.actionPreview.setIcon(QIcon.fromTheme('x-office-document'))
		else:
			self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png'))
		self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L,
		trigbool=self.enableLivePreview)
		menuPreview = QMenu()
		menuPreview.addAction(self.actionLivePreview)
		self.actionPreview.setMenu(menuPreview)
		self.actionTableMode = self.act(self.tr('Table editing mode'),
			shct=Qt.CTRL+Qt.Key_T,
			trigbool=lambda x: self.currentTab.editBox.enableTableMode(x))
		if ReTextFakeVimHandler:
			self.actionFakeVimMode = self.act(self.tr('FakeVim mode'),
				shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode)
			if globalSettings.useFakeVim:
				self.actionFakeVimMode.setChecked(True)
				self.enableFakeVimMode(True)
		self.actionFullScreen = self.act(self.tr('Fullscreen mode'), 'view-fullscreen',
			shct=Qt.Key_F11, trigbool=self.enableFullScreen)
		self.actionFullScreen.setPriority(QAction.LowPriority)
		self.actionConfig = self.act(self.tr('Preferences'), icon='preferences-system',
			trig=self.openConfigDialog)
		self.actionConfig.setMenuRole(QAction.PreferencesRole)
		self.actionSaveHtml = self.act('HTML', 'text-html', self.saveFileHtml)
		self.actionPdf = self.act('PDF', 'application-pdf', self.savePdf)
		self.actionOdf = self.act('ODT', 'x-office-document', self.saveOdf)
		self.getExportExtensionsList()
		self.actionQuit = self.act(self.tr('Quit'), 'application-exit', shct=QKeySequence.Quit)
		self.actionQuit.setMenuRole(QAction.QuitRole)
		self.actionQuit.triggered.connect(self.close)
		self.actionUndo = self.act(self.tr('Undo'), 'edit-undo',
			lambda: self.currentTab.editBox.undo(), shct=QKeySequence.Undo)
		self.actionRedo = self.act(self.tr('Redo'), 'edit-redo',
			lambda: self.currentTab.editBox.redo(), shct=QKeySequence.Redo)
		self.actionCopy = self.act(self.tr('Copy'), 'edit-copy',
			lambda: self.currentTab.editBox.copy(), shct=QKeySequence.Copy)
		self.actionCut = self.act(self.tr('Cut'), 'edit-cut',
			lambda: self.currentTab.editBox.cut(), shct=QKeySequence.Cut)
		self.actionPaste = self.act(self.tr('Paste'), 'edit-paste',
			lambda: self.currentTab.editBox.paste(), shct=QKeySequence.Paste)
		self.actionUndo.setEnabled(False)
		self.actionRedo.setEnabled(False)
		self.actionCopy.setEnabled(False)
		self.actionCut.setEnabled(False)
		qApp = QApplication.instance()
		qApp.clipboard().dataChanged.connect(self.clipboardDataChanged)
		self.clipboardDataChanged()
		if enchant is not None:
			self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck)
			self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale)
		self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit)
		if ReTextWebPreview is None:
			globalSettings.useWebKit = False
			self.actionWebKit.setEnabled(False)
		self.actionWebKit.setChecked(globalSettings.useWebKit)
		self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir)
		self.actionFind = self.act(self.tr('Next'), 'go-next', self.find,
			shct=QKeySequence.FindNext)
		self.actionFindPrev = self.act(self.tr('Previous'), 'go-previous',
			lambda: self.find(back=True), shct=QKeySequence.FindPrevious)
		self.actionReplace = self.act(self.tr('Replace'), 'edit-find-replace',
			lambda: self.find(replace=True))
		self.actionReplaceAll = self.act(self.tr('Replace all'), trig=self.replaceAll)
		menuReplace = QMenu()
		menuReplace.addAction(self.actionReplaceAll)
		self.actionReplace.setMenu(menuReplace)
		self.actionCloseSearch = self.act(self.tr('Close'), 'window-close',
			lambda: self.searchBar.setVisible(False))
		self.actionCloseSearch.setPriority(QAction.LowPriority)
		self.actionHelp = self.act(self.tr('Get help online'), 'help-contents', self.openHelp)
		self.aboutWindowTitle = self.tr('About ReText')
		self.actionAbout = self.act(self.aboutWindowTitle, 'help-about', self.aboutDialog)
		self.actionAbout.setMenuRole(QAction.AboutRole)
		self.actionAboutQt = self.act(self.tr('About Qt'))
		self.actionAboutQt.setMenuRole(QAction.AboutQtRole)
		self.actionAboutQt.triggered.connect(qApp.aboutQt)
		availableMarkups = markups.get_available_markups()
		if not availableMarkups:
			print('Warning: no markups are available!')
		if len(availableMarkups) > 1:
			self.chooseGroup = QActionGroup(self)
			markupActions = []
			for markup in availableMarkups:
				markupAction = self.act(markup.name, trigbool=self.markupFunction(markup))
				if markup.name == globalSettings.defaultMarkup:
					markupAction.setChecked(True)
				self.chooseGroup.addAction(markupAction)
				markupActions.append(markupAction)
		self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold,
			trig=lambda: self.insertFormatting('bold'))
		self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic,
			trig=lambda: self.insertFormatting('italic'))
		self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline,
			trig=lambda: self.insertFormatting('underline'))
		self.usefulTags = ('header', 'italic', 'bold', 'underline', 'numbering',
			'bullets', 'image', 'link', 'inline code', 'code block', 'blockquote')
		self.usefulChars = ('deg', 'divide', 'dollar', 'hellip', 'laquo', 'larr',
			'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo',
			'rarr', 'rsquo', 'times')
		self.formattingBox = QComboBox(self.editBar)
		self.formattingBox.addItem(self.tr('Formatting'))
		self.formattingBox.addItems(self.usefulTags)
		self.formattingBox.activated[str].connect(self.insertFormatting)
		self.symbolBox = QComboBox(self.editBar)
		self.symbolBox.addItem(self.tr('Symbols'))
		self.symbolBox.addItems(self.usefulChars)
		self.symbolBox.activated.connect(self.insertSymbol)
		self.updateStyleSheet()
		menubar = self.menuBar()
		menuFile = menubar.addMenu(self.tr('File'))
		menuEdit = menubar.addMenu(self.tr('Edit'))
		menuHelp = menubar.addMenu(self.tr('Help'))
		menuFile.addAction(self.actionNew)
		menuFile.addAction(self.actionOpen)
		self.menuRecentFiles = menuFile.addMenu(self.tr('Open recent'))
		self.menuRecentFiles.aboutToShow.connect(self.updateRecentFiles)
		menuFile.addAction(self.actionShow)
		menuFile.addAction(self.actionSetEncoding)
		menuFile.addAction(self.actionReload)
		menuFile.addSeparator()
		menuFile.addAction(self.actionSave)
		menuFile.addAction(self.actionSaveAs)
		menuFile.addSeparator()
		menuFile.addAction(self.actionNextTab)
		menuFile.addAction(self.actionPrevTab)
		menuFile.addSeparator()
		menuExport = menuFile.addMenu(self.tr('Export'))
		menuExport.addAction(self.actionSaveHtml)
		menuExport.addAction(self.actionOdf)
		menuExport.addAction(self.actionPdf)
		if self.extensionActions:
			menuExport.addSeparator()
			for action, mimetype in self.extensionActions:
				menuExport.addAction(action)
			menuExport.aboutToShow.connect(self.updateExtensionsVisibility)
		menuFile.addAction(self.actionPrint)
		menuFile.addAction(self.actionPrintPreview)
		menuFile.addSeparator()
		menuFile.addAction(self.actionQuit)
		menuEdit.addAction(self.actionUndo)
		menuEdit.addAction(self.actionRedo)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionCut)
		menuEdit.addAction(self.actionCopy)
		menuEdit.addAction(self.actionPaste)
		menuEdit.addSeparator()
		if enchant is not None:
			menuSC = menuEdit.addMenu(self.tr('Spell check'))
			menuSC.addAction(self.actionEnableSC)
			menuSC.addAction(self.actionSetLocale)
		menuEdit.addAction(self.actionSearch)
		menuEdit.addAction(self.actionChangeEditorFont)
		menuEdit.addAction(self.actionChangePreviewFont)
		menuEdit.addSeparator()
		if len(availableMarkups) > 1:
			self.menuMode = menuEdit.addMenu(self.tr('Default markup'))
			for markupAction in markupActions:
				self.menuMode.addAction(markupAction)
		menuFormat = menuEdit.addMenu(self.tr('Formatting'))
		menuFormat.addAction(self.actionBold)
		menuFormat.addAction(self.actionItalic)
		menuFormat.addAction(self.actionUnderline)
		menuEdit.addAction(self.actionWebKit)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionViewHtml)
		menuEdit.addAction(self.actionPreview)
		menuEdit.addAction(self.actionTableMode)
		if ReTextFakeVimHandler:
			menuEdit.addAction(self.actionFakeVimMode)
		menuEdit.addSeparator()
		menuEdit.addAction(self.actionFullScreen)
		menuEdit.addAction(self.actionConfig)
		menuHelp.addAction(self.actionHelp)
		menuHelp.addSeparator()
		menuHelp.addAction(self.actionAbout)
		menuHelp.addAction(self.actionAboutQt)
		toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		toolBar.addAction(self.actionNew)
		toolBar.addSeparator()
		toolBar.addAction(self.actionOpen)
		toolBar.addAction(self.actionSave)
		toolBar.addAction(self.actionPrint)
		toolBar.addSeparator()
		toolBar.addAction(self.actionPreview)
		toolBar.addAction(self.actionFullScreen)
		self.editBar.addAction(self.actionUndo)
		self.editBar.addAction(self.actionRedo)
		self.editBar.addSeparator()
		self.editBar.addAction(self.actionCut)
		self.editBar.addAction(self.actionCopy)
		self.editBar.addAction(self.actionPaste)
		self.editBar.addSeparator()
		self.editBar.addWidget(self.formattingBox)
		self.editBar.addWidget(self.symbolBox)
		self.searchEdit = QLineEdit(self.searchBar)
		self.searchEdit.setPlaceholderText(self.tr('Search'))
		self.searchEdit.returnPressed.connect(self.find)
		self.replaceEdit = QLineEdit(self.searchBar)
		self.replaceEdit.setPlaceholderText(self.tr('Replace with'))
		self.replaceEdit.returnPressed.connect(self.find)
		self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar)
		self.searchBar.addWidget(self.searchEdit)
		self.searchBar.addWidget(self.replaceEdit)
		self.searchBar.addSeparator()
		self.searchBar.addWidget(self.csBox)
		self.searchBar.addAction(self.actionFindPrev)
		self.searchBar.addAction(self.actionFind)
		self.searchBar.addAction(self.actionReplace)
		self.searchBar.addAction(self.actionCloseSearch)
		self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		self.searchBar.setVisible(False)
		self.autoSaveEnabled = globalSettings.autoSave
		if self.autoSaveEnabled:
			timer = QTimer(self)
			timer.start(60000)
			timer.timeout.connect(self.saveAll)
		self.ind = None
		if enchant is not None:
			self.sl = globalSettings.spellCheckLocale
			try:
				enchant.Dict(self.sl or None)
			except enchant.errors.Error as e:
				print(e, file=sys.stderr)
				globalSettings.spellCheck = False
			if globalSettings.spellCheck:
				self.actionEnableSC.setChecked(True)
		self.fileSystemWatcher = QFileSystemWatcher()
		self.fileSystemWatcher.fileChanged.connect(self.fileChanged)

	def restoreLastOpenedFiles(self):
		for file in readListFromSettings("lastFileList"):
			self.openFileWrapper(file)

		# Show the tab of last opened file
		lastTabIndex = globalSettings.lastTabIndex
		if lastTabIndex >= 0 and lastTabIndex < self.tabWidget.count():
			self.tabWidget.setCurrentIndex(lastTabIndex)

	def iterateTabs(self):
		for i in range(self.tabWidget.count()):
			yield self.tabWidget.widget(i)

	def updateStyleSheet(self):
		if globalSettings.styleSheet:
			sheetfile = QFile(globalSettings.styleSheet)
			sheetfile.open(QIODevice.ReadOnly)
			self.ss = QTextStream(sheetfile).readAll()
			sheetfile.close()
		else:
			palette = QApplication.palette()
			self.ss = 'html { color: %s; }\n' % palette.color(QPalette.WindowText).name()
			self.ss += 'td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }\n'
			self.ss += 'table { border-collapse: collapse; }\n'

	def initTabWidget(self):
		def dragEnterEvent(e):
			e.acceptProposedAction()
		def dropEvent(e):
			fn = bytes(e.mimeData().data('text/plain')).decode().rstrip()
			if fn.startswith('file:'):
				fn = QUrl(fn).toLocalFile()
			self.openFileWrapper(fn)
		self.tabWidget.setTabsClosable(True)
		self.tabWidget.setAcceptDrops(True)
		self.tabWidget.setMovable(True)
		self.tabWidget.dragEnterEvent = dragEnterEvent
		self.tabWidget.dropEvent = dropEvent
		if hasattr(self.tabWidget, 'setTabBarAutoHide'):
			self.tabWidget.setTabBarAutoHide(globalSettings.tabBarAutoHide)

	def act(self, name, icon=None, trig=None, trigbool=None, shct=None):
		if not isinstance(shct, QKeySequence):
			shct = QKeySequence(shct)
		if icon:
			action = QAction(self.actIcon(icon), name, self)
		else:
			action = QAction(name, self)
		if trig:
			action.triggered.connect(trig)
		elif trigbool:
			action.setCheckable(True)
			action.triggered[bool].connect(trigbool)
		if shct:
			action.setShortcut(shct)
		return action

	def actIcon(self, name):
		return QIcon.fromTheme(name, QIcon(icon_path+name+'.png'))

	def printError(self):
		import traceback
		print('Exception occurred while parsing document:', file=sys.stderr)
		traceback.print_exc()


	def tabFileNameChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		filename of the current tab has changed.
		'''
		if tab == self.currentTab:
			if tab.fileName:
				self.setWindowTitle("")
				self.setWindowFilePath(tab.fileName)
				self.tabWidget.setTabText(self.ind, tab.getBaseName())
				self.tabWidget.setTabToolTip(self.ind, tab.fileName)
				QDir.setCurrent(QFileInfo(tab.fileName).dir().path())
			else:
				self.setWindowFilePath('')
				self.setWindowTitle(self.tr('New document') + '[*]')

			canReload = bool(tab.fileName) and not self.autoSaveActive(tab)
			self.actionSetEncoding.setEnabled(canReload)
			self.actionReload.setEnabled(canReload)

	def tabActiveMarkupChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		active markup class of the current tab has changed.
		'''
		if tab == self.currentTab:
			markupClass = tab.getActiveMarkupClass()
			dtMarkdown = (markupClass == markups.MarkdownMarkup)
			dtMkdOrReST = dtMarkdown or (markupClass == markups.ReStructuredTextMarkup)
			self.formattingBox.setEnabled(dtMarkdown)
			self.symbolBox.setEnabled(dtMarkdown)
			self.actionUnderline.setEnabled(dtMarkdown)
			self.actionBold.setEnabled(dtMkdOrReST)
			self.actionItalic.setEnabled(dtMkdOrReST)

	def tabModificationStateChanged(self, tab):
		'''
		Perform all UI state changes that need to be done when the
		modification state of the current tab has changed.
		'''
		if tab == self.currentTab:
			changed = tab.editBox.document().isModified()
			if self.autoSaveActive(tab):
				changed = False
			self.actionSave.setEnabled(changed)
			self.setWindowModified(changed)

	def createTab(self, fileName):
		self.currentTab = ReTextTab(self, fileName,
			previewState=int(globalSettings.livePreviewByDefault))
		self.currentTab.fileNameChanged.connect(lambda: self.tabFileNameChanged(self.currentTab))
		self.currentTab.modificationStateChanged.connect(lambda: self.tabModificationStateChanged(self.currentTab))
		self.currentTab.activeMarkupChanged.connect(lambda: self.tabActiveMarkupChanged(self.currentTab))
		self.tabWidget.addTab(self.currentTab, self.tr("New document"))
		self.currentTab.updateBoxesVisibility()

	def closeTab(self, ind):
		if self.maybeSave(ind):
			if self.tabWidget.count() == 1:
				self.createTab("")
			closedTab = self.tabWidget.widget(ind)
			if closedTab.fileName:
				self.fileSystemWatcher.removePath(closedTab.fileName)
			self.tabWidget.removeTab(ind)
			closedTab.deleteLater()

	def changeIndex(self, ind):
		'''
		This function is called when a different tab is selected.
		It changes the state of the window to mirror the current state
		of the newly selected tab. Future changes to this state will be
		done in response to signals emitted by the tab, to which the
		window was subscribed when the tab was created. The window is
		subscribed to all tabs like this, but only the active tab will
		logically generate these signals.
		Aside from the above this function also calls the handlers for
		the other changes that are implied by a tab switch: filename
		change, modification state change and active markup change.
		'''
		self.currentTab = self.tabWidget.currentWidget()
		editBox = self.currentTab.editBox
		previewState = self.currentTab.previewState
		self.actionUndo.setEnabled(editBox.document().isUndoAvailable())
		self.actionRedo.setEnabled(editBox.document().isRedoAvailable())
		self.actionCopy.setEnabled(editBox.textCursor().hasSelection())
		self.actionCut.setEnabled(editBox.textCursor().hasSelection())
		self.actionPreview.setChecked(previewState >= PreviewLive)
		self.actionLivePreview.setChecked(previewState == PreviewLive)
		self.actionTableMode.setChecked(editBox.tableModeEnabled)
		self.editBar.setEnabled(previewState < PreviewNormal)
		self.ind = ind
		editBox.setFocus(Qt.OtherFocusReason)

		self.tabFileNameChanged(self.currentTab)
		self.tabModificationStateChanged(self.currentTab)
		self.tabActiveMarkupChanged(self.currentTab)

	def changeEditorFont(self):
		font, ok = QFontDialog.getFont(globalSettings.editorFont, self)
		if ok:
			globalSettings.editorFont = font
			for tab in self.iterateTabs():
				tab.editBox.updateFont()

	def changePreviewFont(self):
		font, ok = QFontDialog.getFont(globalSettings.font, self)
		if ok:
			globalSettings.font = font
			for tab in self.iterateTabs():
				tab.triggerPreviewUpdate()

	def preview(self, viewmode):
		self.currentTab.previewState = viewmode * 2
		self.actionLivePreview.setChecked(False)
		self.editBar.setDisabled(viewmode)
		self.currentTab.updateBoxesVisibility()

	def enableLivePreview(self, livemode):
		self.currentTab.previewState = int(livemode)
		self.actionPreview.setChecked(livemode)
		self.editBar.setEnabled(True)
		self.currentTab.updateBoxesVisibility()

	def enableWebKit(self, enable):
		globalSettings.useWebKit = enable
		for tab in self.iterateTabs():
			tab.previewBox.disconnectExternalSignals()
			tab.previewBox.setParent(None)
			tab.previewBox.deleteLater()
			tab.previewBox = tab.createPreviewBox(tab.editBox)
			tab.previewBox.setMinimumWidth(125)
			tab.addWidget(tab.previewBox)
			tab.setSizes((50, 50))
			tab.triggerPreviewUpdate()
			tab.updateBoxesVisibility()

	def enableCopy(self, copymode):
		self.actionCopy.setEnabled(copymode)
		self.actionCut.setEnabled(copymode)

	def enableFullScreen(self, yes):
		if yes:
			self.showFullScreen()
		else:
			self.showNormal()

	def openConfigDialog(self):
		dlg = ConfigDialog(self)
		dlg.setWindowTitle(self.tr('Preferences'))
		dlg.show()

	def enableFakeVimMode(self, yes):
		globalSettings.useFakeVim = yes
		if yes:
			FakeVimMode.init(self)
			for tab in self.iterateTabs():
				tab.editBox.installFakeVimHandler()
		else:
			FakeVimMode.exit(self)

	def enableSpellCheck(self, yes):
		try:
			dict = enchant.Dict(self.sl or None)
		except enchant.errors.Error as e:
			QMessageBox.warning(self, '', str(e))
			self.actionEnableSC.setChecked(False)
			yes = False
		self.setAllDictionaries(dict if yes else None)
		globalSettings.spellCheck = yes

	def setAllDictionaries(self, dictionary):
		for tab in self.iterateTabs():
			hl = tab.highlighter
			hl.dictionary = dictionary
			hl.rehighlight()

	def changeLocale(self):
		localedlg = LocaleDialog(self, defaultText=self.sl)
		if localedlg.exec() != QDialog.Accepted:
			return
		sl = localedlg.localeEdit.text()
		try:
			enchant.Dict(sl or None)
		except enchant.errors.Error as e:
			QMessageBox.warning(self, '', str(e))
		else:
			self.sl = sl or None
			self.enableSpellCheck(self.actionEnableSC.isChecked())
			if localedlg.checkBox.isChecked():
				globalSettings.spellCheckLocale = sl

	def searchBarVisibilityChanged(self, visible):
		self.actionSearch.setChecked(visible)
		if visible:
			self.searchEdit.setFocus(Qt.ShortcutFocusReason)

	def find(self, back=False, replace=False):
		flags = QTextDocument.FindFlags()
		if back:
			flags |= QTextDocument.FindBackward
		if self.csBox.isChecked():
			flags |= QTextDocument.FindCaseSensitively
		text = self.searchEdit.text()
		replaceText = self.replaceEdit.text() if replace else None
		found = self.currentTab.find(text, flags, replaceText=replaceText)
		self.setSearchEditColor(found)

	def replaceAll(self):
		text = self.searchEdit.text()
		replaceText = self.replaceEdit.text()
		found = self.currentTab.replaceAll(text, replaceText)
		self.setSearchEditColor(found)

	def setSearchEditColor(self, found):
		palette = self.searchEdit.palette()
		palette.setColor(QPalette.Active, QPalette.Base,
		                 Qt.white if found else QColor(255, 102, 102))
		self.searchEdit.setPalette(palette)

	def showInDir(self):
		if self.currentTab.fileName:
			path = QFileInfo(self.currentTab.fileName).path()
			QDesktopServices.openUrl(QUrl.fromLocalFile(path))
		else:
			QMessageBox.warning(self, '', self.tr("Please, save the file somewhere."))

	def moveToTopOfRecentFileList(self, fileName):
		if fileName:
			files = readListFromSettings("recentFileList")
			if fileName in files:
				files.remove(fileName)
			files.insert(0, fileName)
			if len(files) > 10:
				del files[10:]
			writeListToSettings("recentFileList", files)

	def createNew(self, text=None):
		self.createTab("")
		self.ind = self.tabWidget.count()-1
		self.tabWidget.setCurrentIndex(self.ind)
		if text:
			self.currentTab.editBox.textCursor().insertText(text)

	def switchTab(self, shift=1):
		self.tabWidget.setCurrentIndex((self.ind + shift) % self.tabWidget.count())

	def updateRecentFiles(self):
		self.menuRecentFiles.clear()
		self.recentFilesActions = []
		filesOld = readListFromSettings("recentFileList")
		files = []
		for f in filesOld:
			if QFile.exists(f):
				files.append(f)
				self.recentFilesActions.append(self.act(f, trig=self.openFunction(f)))
		writeListToSettings("recentFileList", files)
		for action in self.recentFilesActions:
			self.menuRecentFiles.addAction(action)

	def markupFunction(self, markup):
		return lambda: self.setDefaultMarkup(markup)

	def openFunction(self, fileName):
		return lambda: self.openFileWrapper(fileName)

	def extensionFunction(self, data):
		return lambda: \
		self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension'])

	def getExportExtensionsList(self):
		extensions = []
		for extsprefix in datadirs:
			extsdir = QDir(extsprefix+'/export-extensions/')
			if extsdir.exists():
				for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'],
				QDir.Files | QDir.Readable):
					extensions.append(self.readExtension(fileInfo.filePath()))
		locale = QLocale.system().name()
		self.extensionActions = []
		for extension in extensions:
			try:
				if ('Name[%s]' % locale) in extension:
					name = extension['Name[%s]' % locale]
				elif ('Name[%s]' % locale.split('_')[0]) in extension:
					name = extension['Name[%s]' % locale.split('_')[0]]
				else:
					name = extension['Name']
				data = {}
				for prop in ('FileFilter', 'DefaultExtension', 'Exec'):
					if 'X-ReText-'+prop in extension:
						data[prop] = extension['X-ReText-'+prop]
					elif prop in extension:
						data[prop] = extension[prop]
					else:
						data[prop] = ''
				action = self.act(name, trig=self.extensionFunction(data))
				if 'Icon' in extension:
					action.setIcon(self.actIcon(extension['Icon']))
				mimetype = extension['MimeType'] if 'MimeType' in extension else None
			except KeyError:
				print('Failed to parse extension: Name is required', file=sys.stderr)
			else:
				self.extensionActions.append((action, mimetype))

	def updateExtensionsVisibility(self):
		markupClass = self.currentTab.getActiveMarkupClass()
		for action in self.extensionActions:
			if markupClass is None:
				action[0].setEnabled(False)
				continue
			mimetype = action[1]
			if mimetype is None:
				enabled = True
			elif markupClass == markups.MarkdownMarkup:
				enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown", "text/markdown"))
			elif markupClass == markups.ReStructuredTextMarkup:
				enabled = (mimetype in ("text/x-retext-rst", "text/x-rst"))
			else:
				enabled = False
			action[0].setEnabled(enabled)

	def readExtension(self, fileName):
		extFile = QFile(fileName)
		extFile.open(QIODevice.ReadOnly)
		extension = {}
		stream = QTextStream(extFile)
		while not stream.atEnd():
			line = stream.readLine()
			if '=' in line:
				index = line.index('=')
				extension[line[:index].rstrip()] = line[index+1:].lstrip()
		extFile.close()
		return extension

	def openFile(self):
		supportedExtensions = ['.txt']
		for markup in markups.get_all_markups():
			supportedExtensions += markup.file_extensions
		fileFilter = ' (' + str.join(' ', ['*'+ext for ext in supportedExtensions]) + ');;'
		fileNames = QFileDialog.getOpenFileNames(self,
			self.tr("Select one or several files to open"), "",
			self.tr("Supported files") + fileFilter + self.tr("All files (*)"))
		for fileName in fileNames[0]:
			self.openFileWrapper(fileName)

	def openFileWrapper(self, fileName):
		if not fileName:
			return
		fileName = QFileInfo(fileName).canonicalFilePath()
		exists = False
		for i, tab in enumerate(self.iterateTabs()):
			if tab.fileName == fileName:
				exists = True
				ex = i
		if exists:
			self.tabWidget.setCurrentIndex(ex)
		elif QFile.exists(fileName):
			noEmptyTab = (
				(self.ind is None) or
				self.currentTab.fileName or
				self.currentTab.editBox.toPlainText() or
				self.currentTab.editBox.document().isModified()
			)
			if noEmptyTab:
				self.createTab(fileName)
				self.ind = self.tabWidget.count()-1
				self.tabWidget.setCurrentIndex(self.ind)
			if fileName:
				self.fileSystemWatcher.addPath(fileName)
			self.currentTab.readTextFromFile(fileName)
			self.moveToTopOfRecentFileList(self.currentTab.fileName)

	def showEncodingDialog(self):
		if not self.maybeSave(self.ind):
			return
		codecsSet = set(bytes(QTextCodec.codecForName(alias).name())
		                for alias in QTextCodec.availableCodecs())
		encoding, ok = QInputDialog.getItem(self, '',
			self.tr('Select file encoding from the list:'),
			[bytes(b).decode() for b in sorted(codecsSet)],
			0, False)
		if ok:
			self.currentTab.readTextFromFile(None, encoding)

	def saveFileAs(self):
		self.saveFile(dlg=True)

	def saveAll(self):
		for tab in self.iterateTabs():
			if tab.fileName and QFileInfo(tab.fileName).isWritable():
				tab.saveTextToFile()

	def saveFile(self, dlg=False):
		fileNameToSave = self.currentTab.fileName

		if (not fileNameToSave) or dlg:
			markupClass = self.currentTab.getActiveMarkupClass()
			if (markupClass is None) or not hasattr(markupClass, 'default_extension'):
				defaultExt = self.tr("Plain text (*.txt)")
				ext = ".txt"
			else:
				defaultExt = self.tr('%s files',
					'Example of final string: Markdown files') \
					% markupClass.name + ' (' + str.join(' ',
					('*'+extension for extension in markupClass.file_extensions)) + ')'
				if markupClass == markups.MarkdownMarkup:
					ext = globalSettings.markdownDefaultFileExtension
				elif markupClass == markups.ReStructuredTextMarkup:
					ext = globalSettings.restDefaultFileExtension
				else:
					ext = markupClass.default_extension
			fileNameToSave = QFileDialog.getSaveFileName(self,
				self.tr("Save file"), "", defaultExt)[0]
			if fileNameToSave:
				if not QFileInfo(fileNameToSave).suffix():
					fileNameToSave += ext
				# Make sure we don't overwrite a file opened in other tab
				for tab in self.iterateTabs():
					if tab is not self.currentTab and tab.fileName == fileNameToSave:
						QMessageBox.warning(self, "",
							self.tr("Cannot save to file which is open in another tab!"))
						return False
				self.actionSetEncoding.setDisabled(self.autoSaveActive())
		if fileNameToSave:
			if self.currentTab.saveTextToFile(fileNameToSave):
				self.moveToTopOfRecentFileList(self.currentTab.fileName)
				return True
			else:
				QMessageBox.warning(self, '',
				self.tr("Cannot save to file because it is read-only!"))
		return False

	def saveHtml(self, fileName):
		if not QFileInfo(fileName).suffix():
			fileName += ".html"
		try:
			_, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False,
				                                              webenv=True)
		except Exception:
			return self.printError()
		htmlFile = QFile(fileName)
		htmlFile.open(QIODevice.WriteOnly)
		html = QTextStream(htmlFile)
		if globalSettings.defaultCodec:
			html.setCodec(globalSettings.defaultCodec)
		html << htmltext
		htmlFile.close()

	def textDocument(self, title, htmltext):
		td = QTextDocument()
		td.setMetaInformation(QTextDocument.DocumentTitle, title)
		if self.ss:
			td.setDefaultStyleSheet(self.ss)
		td.setHtml(htmltext)
		td.setDefaultFont(globalSettings.font)
		return td

	def saveOdf(self):
		title, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=True,
		                                                          webenv=False)
		try:
			document = self.textDocument(title, htmltext)
		except Exception:
			return self.printError()
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Export document to ODT"), "",
			self.tr("OpenDocument text files (*.odt)"))[0]
		if not QFileInfo(fileName).suffix():
			fileName += ".odt"
		writer = QTextDocumentWriter(fileName)
		writer.setFormat(b"odf")
		writer.write(document)

	def saveFileHtml(self):
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Save file"), "",
			self.tr("HTML files (*.html *.htm)"))[0]
		if fileName:
			self.saveHtml(fileName)

	def getDocumentForPrint(self, title, htmltext, preview):
		if globalSettings.useWebKit:
			return preview
		try:
			return self.textDocument(title, htmltext)
		except Exception:
			self.printError()

	def standardPrinter(self, title):
		printer = QPrinter(QPrinter.HighResolution)
		printer.setDocName(title)
		printer.setCreator('ReText %s' % app_version)
		return printer

	def savePdf(self):
		fileName = QFileDialog.getSaveFileName(self,
			self.tr("Export document to PDF"),
			"", self.tr("PDF files (*.pdf)"))[0]
		if fileName:
			if not QFileInfo(fileName).suffix():
				fileName += ".pdf"
			title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										        webenv=False)
			printer = self.standardPrinter(title)
			printer.setOutputFormat(QPrinter.PdfFormat)
			printer.setOutputFileName(fileName)
			document = self.getDocumentForPrint(title, htmltext, preview)
			if document != None:
				document.print(printer)

	def printFile(self):
		title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										webenv=False)
		printer = self.standardPrinter(title)
		dlg = QPrintDialog(printer, self)
		dlg.setWindowTitle(self.tr("Print document"))
		if (dlg.exec() == QDialog.Accepted):
			document = self.getDocumentForPrint(title, htmltext, preview)
			if document != None:
				document.print(printer)

	def printPreview(self):
		title, htmltext, preview = self.currentTab.getDocumentForExport(includeStyleSheet=True,
										webenv=False)
		document = self.getDocumentForPrint(title, htmltext, preview)
		if document is None:
			return
		printer = self.standardPrinter(title)
		preview = QPrintPreviewDialog(printer, self)
		preview.paintRequested.connect(document.print)
		preview.exec()

	def runExtensionCommand(self, command, filefilter, defaultext):
		import shlex
		of = ('%of' in command)
		html = ('%html' in command)
		if of:
			if defaultext and not filefilter:
				filefilter = '*'+defaultext
			fileName = QFileDialog.getSaveFileName(self,
				self.tr('Export document'), '', filefilter)[0]
			if not fileName:
				return
			if defaultext and not QFileInfo(fileName).suffix():
				fileName += defaultext
		else:
			fileName = 'out' + defaultext
		basename = '.%s.retext-temp' % self.currentTab.getBaseName()
		if html:
			tmpname = basename+'.html'
			self.saveHtml(tmpname)
		else:
			tmpname = basename + self.currentTab.getActiveMarkupClass().default_extension
			self.currentTab.writeTextToFile(tmpname)
		command = command.replace('%of', shlex.quote(fileName))
		command = command.replace('%html' if html else '%if', shlex.quote(tmpname))
		try:
			Popen(str(command), shell=True).wait()
		except Exception as error:
			errorstr = str(error)
			QMessageBox.warning(self, '', self.tr('Failed to execute the command:')
			+ '\n' + errorstr)
		QFile(tmpname).remove()

	def autoSaveActive(self, tab=None):
		tab = tab if tab else self.currentTab
		return bool(self.autoSaveEnabled and tab.fileName and
			    QFileInfo(tab.fileName).isWritable())

	def clipboardDataChanged(self):
		mimeData = QApplication.instance().clipboard().mimeData()
		if mimeData is not None:
			self.actionPaste.setEnabled(mimeData.hasText() or mimeData.hasImage())

	def insertFormatting(self, formatting):
		cursor = self.currentTab.editBox.textCursor()
		text = cursor.selectedText()
		moveCursorTo = None

		def c(cursor):
			nonlocal moveCursorTo
			moveCursorTo = cursor.position()

		def ensurenl(cursor):
			if not cursor.atBlockStart():
				cursor.insertText('\n\n')

		toinsert = {
			'header': (ensurenl, '# ', text),
			'italic': ('*', text, c, '*'),
			'bold': ('**', text, c, '**'),
			'underline': ('<u>', text, c, '</u>'),
			'numbering': (ensurenl, ' 1. ', text),
			'bullets': (ensurenl, '  * ', text),
			'image': ('![', text or self.tr('Alt text'), c, '](', self.tr('URL'), ')'),
			'link': ('[', text or self.tr('Link text'), c, '](', self.tr('URL'), ')'),
			'inline code': ('`', text, c, '`'),
			'code block': (ensurenl, '    ', text),
			'blockquote': (ensurenl, '> ', text),
		}

		if formatting not in toinsert:
			return

		cursor.beginEditBlock()
		for token in toinsert[formatting]:
			if callable(token):
				token(cursor)
			else:
				cursor.insertText(token)
		cursor.endEditBlock()

		self.formattingBox.setCurrentIndex(0)
		# Bring back the focus on the editor
		self.currentTab.editBox.setFocus(Qt.OtherFocusReason)

		if moveCursorTo:
			cursor.setPosition(moveCursorTo)
			self.currentTab.editBox.setTextCursor(cursor)

	def insertSymbol(self, num):
		if num:
			self.currentTab.editBox.insertPlainText('&'+self.usefulChars[num-1]+';')
		self.symbolBox.setCurrentIndex(0)

	def fileChanged(self, fileName):
		ind = None
		for testind, tab in enumerate(self.iterateTabs()):
			if tab.fileName == fileName:
				ind = testind
		if ind is None:
			self.fileSystemWatcher.removePath(fileName)
		self.tabWidget.setCurrentIndex(ind)
		if not QFile.exists(fileName):
			self.currentTab.editBox.document().setModified(True)
			QMessageBox.warning(self, '', self.tr(
				'This file has been deleted by other application.\n'
				'Please make sure you save the file before exit.'))
		elif not self.currentTab.editBox.document().isModified():
			# File was not modified in ReText, reload silently
			self.currentTab.readTextFromFile()
		else:
			text = self.tr(
				'This document has been modified by other application.\n'
				'Do you want to reload the file (this will discard all '
				'your changes)?\n')
			if self.autoSaveEnabled:
				text += self.tr(
					'If you choose to not reload the file, auto save mode will '
					'be disabled for this session to prevent data loss.')
			messageBox = QMessageBox(QMessageBox.Warning, '', text)
			reloadButton = messageBox.addButton(self.tr('Reload'), QMessageBox.YesRole)
			messageBox.addButton(QMessageBox.Cancel)
			messageBox.exec()
			if messageBox.clickedButton() is reloadButton:
				self.currentTab.readTextFromFile()
			else:
				self.autoSaveEnabled = False
				self.currentTab.editBox.document().setModified(True)
		if fileName not in self.fileSystemWatcher.files():
			# https://github.com/retext-project/retext/issues/137
			self.fileSystemWatcher.addPath(fileName)

	def maybeSave(self, ind):
		tab = self.tabWidget.widget(ind)
		if self.autoSaveActive(tab):
			tab.saveTextToFile()
			return True
		if not tab.editBox.document().isModified():
			return True
		self.tabWidget.setCurrentIndex(ind)
		ret = QMessageBox.warning(self, '',
			self.tr("The document has been modified.\nDo you want to save your changes?"),
			QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
		if ret == QMessageBox.Save:
			return self.saveFile(False)
		elif ret == QMessageBox.Cancel:
			return False
		return True

	def closeEvent(self, closeevent):
		for ind in range(self.tabWidget.count()):
			if not self.maybeSave(ind):
				return closeevent.ignore()
		if globalSettings.saveWindowGeometry and not self.isMaximized():
			globalSettings.windowGeometry = self.saveGeometry()
		if globalSettings.openLastFilesOnStartup:
			files = [tab.fileName for tab in self.iterateTabs()]
			writeListToSettings("lastFileList", files)
			globalSettings.lastTabIndex = self.tabWidget.currentIndex()
		closeevent.accept()

	def viewHtml(self):
		htmlDlg = HtmlDialog(self)
		try:
			_, htmltext, _ = self.currentTab.getDocumentForExport(includeStyleSheet=False,
			                                                      webenv=False)
		except Exception:
			return self.printError()
		winTitle = self.currentTab.getBaseName()
		htmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+")")
		htmlDlg.textEdit.setPlainText(htmltext.rstrip())
		htmlDlg.hl.rehighlight()
		htmlDlg.show()
		htmlDlg.raise_()
		htmlDlg.activateWindow()

	def openHelp(self):
		QDesktopServices.openUrl(QUrl('https://github.com/retext-project/retext/wiki'))

	def aboutDialog(self):
		QMessageBox.about(self, self.aboutWindowTitle,
		'<p><b>' + (self.tr('ReText %s (using PyMarkups %s)') % (app_version, markups.__version__))
		+'</b></p>' + self.tr('Simple but powerful editor'
		' for Markdown and reStructuredText')
		+'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011').replace('2011', '2011–2016')
		+'<br><a href="https://github.com/retext-project/retext">'+self.tr('Website')
		+'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">'
		+self.tr('Markdown syntax')
		+'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">'
		+self.tr('reStructuredText syntax')+'</a></p>')

	def setDefaultMarkup(self, markupClass):
		globalSettings.defaultMarkup = markupClass.name
		for tab in self.iterateTabs():
			if not tab.fileName:
				tab.updateActiveMarkupClass()
예제 #41
0
class MainWindow(TestableMainWindow):

    # -------------------------------------------------------------------------
    def __init__(self, test_mode=False):
        super(MainWindow, self).__init__(None)

        self.setWindowIcon(QIcon(img('editor/editor.png')))

        self.cfg = Config()
        self._tabs = QTabWidget()
        self._actions: Dict[str, QAction] = {}
        self._menus: Dict[str, QMenu] = {}
        self._make_actions()
        self._spell = SpellChecker(enabled=not test_mode)
        self._init_ui()

    # -------------------------------------------------------------------------
    def _actions_data(self):
        about_qt = QApplication.instance().aboutQt
        for name, title, triggered in (
            ("new", self.tr("New"), lambda: self.open_file()),
            ("open", self.tr("Open"), self.open),
            ("save", self.tr("Save"), self.save),
            ("save_as", self.tr("Save as ..."), self.saveas),
            ("exit", self.tr("Exit"), self.close),
            ("about", self.tr("About"), self.about),
            ("about_qt", self.tr("About Qt"), about_qt),
            ("help", self.tr("User manual"), lambda: self.help()),
            ("eng", self.tr("English"), lambda: self.set_lang("en_EN")),
            ("rus", self.tr("Russian"), lambda: self.set_lang("ru_RU")),
            ("text", self.tr("Only text"), lambda: self.set_format("txt")),
            ("html", self.tr("HTML"), lambda: self.set_format("html")),
            ("no-syntax", self.tr("--no--"),
             lambda: self.set_syntax("--no--")),
            ("python", self.tr("Python"), lambda: self.set_syntax("Python")),
            ("sql", self.tr("SQL"), lambda: self.set_syntax("SQL")),
            ("invisible-symbol", self.tr("Show/hide invisible symbol"),
             self.set_invisible_symbol),
            ("read-only", self.tr("Read only"), self._read_only),
            ("word-wrap", self.tr("Word wrap"), self.word_wrap),
            ("rus-spell", self.tr("russian language"),
             lambda x: self._spell.set_enabled("rus", x)),
            ("eng-spell", self.tr("english language"),
             lambda x: self._spell.set_enabled("eng", x)),
        ):
            yield name, title, triggered

    # -------------------------------------------------------------------------
    def _read_only(self):
        if not self._tabs.count():  # pragma: no cover
            return
        w = self._tabs.widget(self._tabs.currentIndex())
        w.set_read_only(not w.is_read_only())
        self.change_tab(self._tabs.currentIndex())

    # -------------------------------------------------------------------------
    def _make_actions(self):
        for name, title, triggered in self._actions_data():
            self._actions[name] = QAction(title, None)
            self._actions[name].setIcon(QIcon(img("editor/" + name)))
            if triggered:
                self._actions[name].triggered.connect(triggered)

    # -------------------------------------------------------------------------
    def retranslate_ui(self):
        for name, title, _ in self._actions_data():
            self._actions[name].setText(title)
            self._actions[name].setStatusTip(title)
            self._actions[name].setToolTip(title)

        self._menus["file"].setTitle(self.tr("&File"))
        self._menus["lang"].setTitle(self.tr("&Language"))
        self._menus["help"].setTitle(self.tr("&Help"))
        self._menus["view"].setTitle(self.tr("&View"))
        self._menus["format"].setTitle(self.tr("&Format"))
        self._menus["syntax"].setTitle(self.tr("&Syntax"))
        self._menus["spell"].setTitle(self.tr("&Check spelling"))

        idx_current = self._tabs.currentIndex()
        idx_help = -1
        for i in range(self._tabs.count()):
            w = self._tabs.widget(i)
            w.retranslate_ui()
            self._tabs.setTabText(i, w.get_name())
            path = (w.get_path() + "/") if not w.is_help_text() else ""
            self._tabs.setTabToolTip(i, f"{path}{w.get_name()}")
            if w.is_help_text():
                idx_help = i

        # if need, reopen user manual with current language
        if idx_help != -1:
            self.close_tab(idx_help)
            self.help(position=idx_help)

        self._tabs.setCurrentIndex(idx_current)
        self.setWindowTitle(self.tr("[Demo] Embedded text editor"))

    # -------------------------------------------------------------------------
    def _init_ui(self):
        self.setWindowTitle(self.tr("[Demo] Embedded text editor"))
        self.setGeometry(800, 150, 1000, 500)

        self._tabs.setTabsClosable(True)
        self._tabs.setMovable(True)
        self._tabs.tabCloseRequested.connect(self.close_tab)
        self._tabs.currentChanged.connect(self.change_tab)
        self.setCentralWidget(self._tabs)

        # Setup the menu
        self._menus["file"] = self.menuBar().addMenu(self.tr("&File"))
        self._menus["view"] = self.menuBar().addMenu(self.tr("&View"))
        self._menus["help"] = self.menuBar().addMenu(self.tr("&Help"))

        # Populate the Menu with Actions
        self._menus["help"].addAction(self._actions["help"])
        self._menus["help"].addSeparator()
        self._menus["help"].addAction(self._actions["about"])
        # self._menus["help"].addAction(self._actions["about_qt"])

        self._menus["file"].addAction(self._actions["new"])
        self._menus["file"].addAction(self._actions["open"])
        self._menus["file"].addAction(self._actions["save"])
        self._menus["file"].addAction(self._actions["save_as"])
        self._menus["file"].addSeparator()

        self._menus["lang"] = self._menus["file"].addMenu(self.tr("&Language"))
        self._menus["lang"].addAction(self._actions["eng"])
        self._menus["lang"].addAction(self._actions["rus"])

        self._menus["file"].addSeparator()
        self._menus["file"].addAction(self._actions["exit"])

        self._menus["format"] = self._menus["view"].addMenu(self.tr("&Format"))
        self._menus["format"].addAction(self._actions["text"])
        self._menus["format"].addAction(self._actions["html"])
        self._menus["syntax"] = self._menus["view"].addMenu(self.tr("&Syntax"))
        self._menus["syntax"].addAction(self._actions["no-syntax"])
        self._menus["syntax"].addAction(self._actions["python"])
        self._menus["syntax"].addAction(self._actions["sql"])
        self._menus["spell"] = self._menus["view"].addMenu(
            self.tr("&Check spelling"))
        self._menus["spell"].addAction(self._actions["eng-spell"])
        self._menus["spell"].addAction(self._actions["rus-spell"])
        self._menus["view"].addSeparator()
        self._menus["view"].addAction(self._actions["word-wrap"])
        self._menus["view"].addAction(self._actions["invisible-symbol"])
        self._menus["view"].addSeparator()
        self._menus["view"].addAction(self._actions["read-only"])

        open_files = json.loads(self.cfg.get("open_files", "{}", system=True))
        for key, (fmt, highlighter) in open_files.items():
            self.open_file(key, fmt=fmt, hl=highlighter)
        if not self._tabs.count():  # pragma: no cover
            self._actions["save"].setEnabled(False)
            self._actions["save_as"].setEnabled(False)

        self._actions["word-wrap"].setCheckable(True)
        self._actions["read-only"].setCheckable(True)

        self._actions["eng-spell"].setCheckable(True)
        self._actions["rus-spell"].setCheckable(True)
        self._actions["eng-spell"].setChecked(True)
        self._actions["rus-spell"].setChecked(True)
        self._actions["eng-spell"].setEnabled(self._spell.enabled("eng"))
        self._actions["rus-spell"].setEnabled(self._spell.enabled("rus"))
        self._menus["spell"].setEnabled(self._spell.enabled("all"))

        self.retranslate_ui()
        self.read_settings()
        self.show()

        if self._tabs.count() > 0:  # pragma: no cover
            self._tabs.widget(self._tabs.currentIndex()).set_focus()
        else:  # pragma: no cover
            self._menus["view"].setEnabled(False)

        if not self._spell.enabled():
            self._menus["spell"].menuAction().setVisible(False)

    # -------------------------------------------------------------------------
    def set_lang(self, locale):
        install_translators(locale)
        self.retranslate_ui()

    # -------------------------------------------------------------------------
    def word_wrap(self):
        if self._tabs.count() > 0:
            self._tabs.widget(self._tabs.currentIndex()).set_word_wrap()

    # -------------------------------------------------------------------------
    def closeEvent(self, event):
        self.write_settings()
        """
        s = (self.tr("This will exit the editor.") + "\n" +
             self.tr("Do you want to continue ?"))
        if yes_no(s, self):
            event.accept()
        else:
            event.ignore()
        """
        open_files = {}
        for i in range(self._tabs.count()):
            w = self._tabs.widget(i)
            if w.is_modified():  # pragma: no cover
                self.save_text_tab(i)
            open_files[w.file_path()] = (w.text_format(False), w.highlighter())
        self.cfg["SYSTEM", "open_files"] = json.dumps(open_files)
        event.accept()

    # -------------------------------------------------------------------------
    def save_text_tab(self, idx_tab):
        w = self._tabs.widget(idx_tab)
        name = w.file_path() if w.file_path() else w.get_name()
        t1 = self.tr("The file")
        t2 = self.tr("is changed")
        t3 = self.tr("Save it ?")
        if w.is_modified():
            if yes_no(f"{t1} <b>{name}</b> {t2}.<br><br>{t3}", self):
                w.save()

    # -------------------------------------------------------------------------
    def close_tab(self, idx_tab):
        self.save_text_tab(idx_tab)
        self._tabs.removeTab(idx_tab)
        if not self._tabs.count():  # pragma: no cover
            self._actions["save"].setEnabled(False)
            self._actions["save_as"].setEnabled(False)
            self._menus["view"].setEnabled(False)

    # -------------------------------------------------------------------------
    def change_tab(self, idx_tab):
        if not self._tabs.count():  # pragma: no cover
            return
        self._menus["view"].setEnabled(True)
        w = self._tabs.widget(idx_tab)
        self._actions["save"].setEnabled(w.is_modified())
        self._tabs.setTabText(idx_tab, w.get_name())
        textmode = w.text_format().upper() != "HTML"
        self._actions["text"].setEnabled(not textmode)
        self._actions["html"].setEnabled(textmode)
        self._actions["word-wrap"].setChecked(w.get_word_wrap())
        self._actions["read-only"].setChecked(w.is_read_only()
                                              or w.is_help_text())
        self._actions["read-only"].setEnabled(not w.is_help_text())
        self._menus["format"].setEnabled(not w.is_read_only())
        self._menus["syntax"].setEnabled(textmode)
        self._menus["spell"].setEnabled(not textmode
                                        and self._spell.enabled("all"))

    # -------------------------------------------------------------------------
    def change_enabled_save(self):
        self.change_tab(self._tabs.currentIndex())

    # -------------------------------------------------------------------------
    def about(self):
        text = self.tr("Demo for 'Embedded text editor'")
        author = self.tr("(C) 2019, Vladimir Rukavishnikov")
        QMessageBox().about(self, self.tr("Information"),
                            f"{text}\n\n{author}")

    # -------------------------------------------------------------------------
    def set_format(self, name_format):
        if self._tabs.count() > 0:
            idx = self._tabs.currentIndex()
            self._tabs.widget(idx).set_text_format(name_format)
            self.change_tab(idx)

    # -------------------------------------------------------------------------
    def set_syntax(self, name_syntax):
        if self._tabs.count() > 0:
            self._tabs.widget(
                self._tabs.currentIndex()).set_highlighter(name_syntax)

    # -------------------------------------------------------------------------
    def set_invisible_symbol(self):
        if self._tabs.count() > 0:
            self._tabs.widget(self._tabs.currentIndex()).set_invisible_symbol()

    # -------------------------------------------------------------------------
    def read_settings(self):
        pos = QPoint(self.cfg.get("MainWindow.X", 800, True),
                     self.cfg.get("MainWindow.Y", 150, True))
        sz = QSize(self.cfg.get("MainWindow.width", 1000, True),
                   self.cfg.get("MainWindow.height", 500, True))
        self.move(pos)
        self.resize(sz)

    # -------------------------------------------------------------------------
    def write_settings(self):
        self.cfg["SYSTEM", "MainWindow.X"] = self.pos().x()
        self.cfg["SYSTEM", "MainWindow.Y"] = self.pos().y()
        self.cfg["SYSTEM", "MainWindow.width"] = self.size().width()
        self.cfg["SYSTEM", "MainWindow.height"] = self.size().height()

    # -------------------------------------------------------------------------
    def open_file(self, path=None, fmt="html", hl=""):
        if path is not None and not os.path.exists(path):
            return

        # after saving config file, need to reload the configuration
        is_config_file = path == self.cfg.get("Config/FilePath", "")
        func_after_save = self.cfg.load if is_config_file else None

        te = TabEdit(self,
                     file_path=path,
                     text_format=fmt,
                     highlighter=hl,
                     func_after_save=func_after_save,
                     spell=self._spell)
        idx = self._tabs.addTab(te, te.get_name())
        self._tabs.setCurrentIndex(idx)
        path = (te.get_path() + "/") if not te.is_help_text() else ""
        self._tabs.setTabToolTip(idx, f"{path}{te.get_name()}")
        te.enabled_save_signal.connect(self.change_enabled_save)
        self._actions["save_as"].setEnabled(bool(self._tabs.count()))

        if te.is_help_text():
            self._read_only()

    # -------------------------------------------------------------------------
    def save(self):
        if self._tabs.currentIndex() >= 0:
            self._tabs.widget(self._tabs.currentIndex()).save()
            self.change_tab(self._tabs.currentIndex())

    # -------------------------------------------------------------------------
    def saveas(self):
        self._tabs.widget(self._tabs.currentIndex()).save_as()
        self.change_tab(self._tabs.currentIndex())

    # -------------------------------------------------------------------------
    def open(self):
        """
        File dialog with selections syntax and file type.
        """
        filedialog = QFileDialog(self)
        filedialog.setOption(QFileDialog.DontUseNativeDialog)
        filedialog.setDefaultSuffix("*.*")
        filedialog.setDirectory(
            self.cfg.get("TextEditor/LastPath", ".", system=True))
        layout = filedialog.layout()

        type_files = [  # type, syntax, is HTML, list of exts
            (self.tr("All files (*)"), self.tr("-- no --"), True, []),
            (self.tr("Python files (*.py *.pyw)"), "Python", False,
             ["py", "pyw"]),
            (self.tr("SQL scripts (*.sql)"), "SQL", False, ["sql"]),
            (self.tr("Text files (*.txt)"), self.tr("-- no --"), False,
             ["txt"]),
        ]
        filedialog.setNameFilters([t[0] for t in type_files])

        syntax = QComboBox()
        __in_cmb = []
        for t in type_files:
            if t[1] not in __in_cmb:
                __in_cmb.append(t[1])
                syntax.addItem(t[1])

        lbl_syntax = QLabel(self.tr("Syntax"))
        format_text = QCheckBox("HTML")
        format_text.setChecked(True)

        col, row = layout.columnCount(), layout.rowCount()
        layout.addWidget(syntax, row, col - 1)
        layout.addWidget(format_text, row, col - 1)
        layout.addWidget(lbl_syntax, row, 0)
        layout.addWidget(syntax, row, col - 2)
        layout.itemAtPosition(row, col - 1).setAlignment(Qt.AlignCenter)

        layout.update()
        layout.activate()

        def _change_syntax_and_type(idx):  # pragma: no cover
            syntax.setCurrentText(type_files[idx][1])
            format_text.setChecked(type_files[idx][2])

        def _filter_selected(name):  # pragma: no cover
            for i, (nm, _, _, _) in enumerate(type_files):
                if name == nm:
                    _change_syntax_and_type(i)

        def _current_changed(name):  # pragma: no cover
            if "." in name:
                ext = name.split(".")[-1].lower()
                for i, (_, _, _, exts) in enumerate(type_files):
                    if ext in exts:
                        _change_syntax_and_type(i)
                        return
            _change_syntax_and_type(0)

        filedialog.currentChanged.connect(_current_changed)
        filedialog.filterSelected.connect(_filter_selected)

        if filedialog.exec_():
            text_format = "html" if format_text.isChecked() else "text"
            path = filedialog.selectedFiles()[0]
            self.open_file(path=path, fmt=text_format, hl=syntax.currentText())
            self.cfg["SYSTEM", "TextEditor/LastPath"] = os.path.dirname(path)

    # -------------------------------------------------------------------------
    def help(self, position=-1):
        """
        Show text description of editor
        """
        # check if already open
        for i in range(self._tabs.count()):
            if self._tabs.widget(i).is_help_text():
                self._tabs.setCurrentIndex(i)
                return

        # open file
        path = os.path.join(os.path.dirname(__file__), "doc")
        lang = "." + get_current_language()
        filepath = f"{path}{os.sep}demoedit{lang}.html"
        if not os.path.exists(filepath):
            filepath = f"{path}{os.sep}demoedit.html"
        if not os.path.exists(filepath):  # pragma: no cover
            return
        self.open_file(filepath, hl="Python")

        if position != -1:
            self._tabs.tabBar().moveTab(self._tabs.count() - 1, position)
예제 #42
0
class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        
        self._info = None
        self._text = ''
        self._convertedtext = ''
        self._encoding = None
        self.mainwindow = parent
        
        self.fromVersionLabel = QLabel()
        self.fromVersion = QLineEdit()
        self.reason = QLabel()
        self.toVersionLabel = QLabel()
        self.toVersion = QLineEdit()
        self.lilyChooser = lilychooser.LilyChooser()
        self.messages = QTextBrowser()
        self.diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)
        self.uni_diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)
        self.copyCheck = QCheckBox(checked=
            QSettings().value('convert_ly/copy_messages', True, bool))
        self.tabw = QTabWidget()
        
        self.tabw.addTab(self.messages, '')
        self.tabw.addTab(self.diff, '')
        self.tabw.addTab(self.uni_diff, '')
        
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Reset | QDialogButtonBox.Save |
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttons.button(QDialogButtonBox.Ok).clicked    .connect(self.accept)
        self.buttons.rejected.connect(self.reject)
        self.buttons.button(QDialogButtonBox.Reset).clicked.connect(self.run)
        self.buttons.button(QDialogButtonBox.Save).clicked.connect(self.saveFile)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        grid = QGridLayout()
        grid.addWidget(self.fromVersionLabel, 0, 0)
        grid.addWidget(self.fromVersion, 0, 1)
        grid.addWidget(self.reason, 0, 2, 1, 3)
        grid.addWidget(self.toVersionLabel, 1, 0)
        grid.addWidget(self.toVersion, 1, 1)
        grid.addWidget(self.lilyChooser, 1, 3, 1, 2)
        
        layout.addLayout(grid)
        layout.addWidget(self.tabw)
        layout.addWidget(self.copyCheck)
        layout.addWidget(widgets.Separator())
        layout.addWidget(self.buttons)
        
        app.translateUI(self)
        qutil.saveDialogSize(self, 'convert_ly/dialog/size', QSize(600, 300))
        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        self.finished.connect(self.saveCopyCheckSetting)
        self.lilyChooser.currentIndexChanged.connect(self.slotLilyPondVersionChanged)
        self.slotLilyPondVersionChanged()
        
    def translateUI(self):
        self.fromVersionLabel.setText(_("From version:"))
        self.toVersionLabel.setText(_("To version:"))
        self.copyCheck.setText(_("Save convert-ly messages in document"))
        self.copyCheck.setToolTip(_(
            "If checked, the messages of convert-ly are appended as a "
            "comment to the end of the document."))
        self.tabw.setTabText(0, _("&Messages"))
        self.tabw.setTabText(1, _("&Changes"))
        self.tabw.setTabText(2, _("&Diff"))
        self.buttons.button(QDialogButtonBox.Reset).setText(_("Run Again"))
        self.buttons.button(QDialogButtonBox.Save).setText(_("Save as file"))
        self.setCaption()
    
    def saveCopyCheckSetting(self):
        QSettings().setValue('convert_ly/copy_messages', self.copyCheck.isChecked())
    
    def readSettings(self):
        font = textformats.formatData('editor').font
        self.diff.setFont(font)
        diffFont = QFont("Monospace")
        diffFont.setStyleHint(QFont.TypeWriter)
        self.uni_diff.setFont(diffFont)
    
    def slotLilyPondVersionChanged(self):
        self.setLilyPondInfo(self.lilyChooser.lilyPondInfo())
    
    def setCaption(self):
        version = self._info and self._info.versionString() or _("<unknown>")
        title = _("Convert-ly from LilyPond {version}").format(version=version)
        self.setWindowTitle(app.caption(title))

    def setLilyPondInfo(self, info):
        self._info = info
        self.setCaption()
        self.toVersion.setText(info.versionString())
        self.setConvertedText()
        self.setDiffText()
        self.messages.clear()
    
    def setConvertedText(self, text=''):
        self._convertedtext = text
        self.buttons.button(QDialogButtonBox.Ok).setEnabled(bool(text))
        if text:
            self.diff.setHtml(htmldiff.htmldiff(
                self._text, text,
                _("Current Document"), _("Converted Document"),
                wrapcolumn=100))
        else:
            self.diff.clear()
            
    def setDiffText(self, text=''):
        if text:
            from_filename = "current"   # TODO: maybe use real filename here
            to_filename = "converted"   # but difflib can choke on non-ascii characters,
                                        # see https://github.com/wbsoft/frescobaldi/issues/674
            difflist = list(difflib.unified_diff(
                    self._text.split('\n'), text.split('\n'), 
                    from_filename, to_filename))
            diffHLstr = self.diffHighl(difflist)
            self.uni_diff.setHtml(diffHLstr)
        else:
            self.uni_diff.clear()
    
    def convertedText(self):
        return self._convertedtext or ''
    
    def setDocument(self, doc):
        v = documentinfo.docinfo(doc).version_string()
        if v:
            self.fromVersion.setText(v)
            self.reason.setText(_("(set in document)"))
        else:
            self.reason.clear()
        self._text = doc.toPlainText()
        self._encoding = doc.encoding() or 'UTF-8'
        self.setConvertedText()
        self.setDiffText()
        
    def run(self):
        """Runs convert-ly (again)."""
        fromVersion = self.fromVersion.text()
        toVersion = self.toVersion.text()
        if not fromVersion or not toVersion:
            self.messages.setPlainText(_(
                "Both 'from' and 'to' versions need to be set."))
            return
        info = self._info
        command = info.toolcommand(info.ly_tool('convert-ly'))
        command += ['-f', fromVersion, '-t', toVersion, '-']
        
        # if the user wants english messages, do it also here: LANGUAGE=C
        env = None
        if os.name == "nt":
            # Python 2.7 subprocess on Windows chokes on unicode in env
            env = util.bytes_environ()
        else:
            env = dict(os.environ)
        if sys.platform.startswith('darwin'):
            try:
                del env['PYTHONHOME']
            except KeyError:
                pass
            try:
                del env['PYTHONPATH']
            except KeyError:
                pass
        if QSettings().value("lilypond_settings/no_translation", False, bool):
            if os.name == "nt":
                # Python 2.7 subprocess on Windows chokes on unicode in env
                env[b'LANGUAGE'] = b'C'
            else:
                env['LANGUAGE'] = 'C'
        
        with qutil.busyCursor():
            try:
                proc = subprocess.Popen(command,
                    env = env,
                    stdin = subprocess.PIPE,
                    stdout = subprocess.PIPE,
                    stderr = subprocess.PIPE)
                out, err = proc.communicate(util.platform_newlines(self._text).encode(self._encoding))
            except OSError as e:
                self.messages.setPlainText(_(
                    "Could not start {convert_ly}:\n\n"
                    "{message}\n").format(convert_ly = command[0], message = e))
                return
            out = util.universal_newlines(out.decode('UTF-8'))
            err = util.universal_newlines(err.decode('UTF-8'))
            self.messages.setPlainText(err)
            self.setConvertedText(out)
            self.setDiffText(out)
            if not out or self._convertedtext == self._text:
                self.messages.append('\n' + _("The document has not been changed."))

    def saveFile(self):
        """Save content in tab as file"""
        tabdata = self.getTabData(self.tabw.currentIndex())
        doc = self.mainwindow.currentDocument()
        orgname = doc.url().toLocalFile()
        filename = os.path.splitext(orgname)[0] + '['+tabdata.filename+']'+'.'+tabdata.ext
        caption = app.caption(_("dialog title", "Save File"))
        filetypes = '{0} (*.txt);;{1} (*.htm);;{2} (*)'.format(_("Text Files"), _("HTML Files"), _("All Files"))
        filename = QFileDialog.getSaveFileName(self.mainwindow, caption, filename, filetypes)[0]
        if not filename:
            return False # cancelled
        with open(filename, 'wb') as f:
            f.write(tabdata.text.encode('utf-8'))

    def getTabData(self, index):
        """Get content of current tab from current index"""
        if index == 0:
            return FileInfo('message', 'txt', self.messages.toPlainText())
        elif index == 1:
            return FileInfo('html-diff', 'html', self.diff.toHtml())
        elif index == 2:
            return FileInfo('uni-diff', 'diff', self.uni_diff.toPlainText())
            
    def diffHighl(self, difflist):
        """Return highlighted version of input."""
        result = []
        for l in difflist:
            if l.startswith('-'):
                s = '<span style="color: red; white-space: pre-wrap;">'
            elif l.startswith('+'):
                s = '<span style="color: green; white-space: pre-wrap;">'
            else:
                s = '<span style="white-space: pre-wrap;">'
            h = l.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            result.append(s + h + '</span>')
        return '<br>'.join(result)
예제 #43
0
class MainWindow(QMainWindow):

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

        self.setGeometry(20, 20, 1324, 1068)
        self.setWindowTitle('qt-Notepad')
        self.setStyleSheet('font-size: 14pt; font-family: Courier;')

        self.show()
        self.init_ui()
        centralWidget = QWidget()
        self.tabs = QTabWidget(centralWidget)
        self.setCentralWidget(self.tabs)
        self.tabs.setTabsClosable(True)
        self.tabs.setMovable(True)
        self.tabs.tabCloseRequested.connect(self.closeTab)
        if filename:
            f = open(filename, 'r')
            filedata = f.read()
            f.close()
            newfile = QTextEdit()
            newfile.setText(filedata)
            i = self.tabs.addTab(newfile, filename)
            self.tabs.setCurrentIndex(i)
        else:
            self.open_file()

    def init_ui(self):

        new_action = QAction('New File', self)
        new_action.setShortcut('Ctrl+N')
        new_action.setStatusTip('Create new file')
        new_action.triggered.connect(self.new_file)

        open_action = QAction('Open...', self)
        open_action.setShortcut('Ctrl+O')
        open_action.setStatusTip('Open a file')
        open_action.triggered.connect(self.open_file)

        save_action = QAction('Save File', self)
        save_action.setShortcut('Ctrl+S')
        save_action.setStatusTip('Save current file')
        save_action.triggered.connect(self.save_file)

        new_save_action = QAction('Save File As...', self)
        new_save_action.setShortcut('Shift+Ctrl+S')
        new_save_action.setStatusTip('Save current file')
        new_save_action.triggered.connect(self.save_file_as)

        close_action = QAction('Close File', self)
        close_action.setShortcut('Ctrl+W')
        close_action.setStatusTip('Close file and exit tab')
        close_action.triggered.connect(self.close_file)

        exit_action = QAction('Exit qt-Notepad', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.setStatusTip('Close Notepad')
        exit_action.triggered.connect(self.close)

        undo_action = QAction('Undo', self)
        undo_action.setShortcut('Ctrl+Z')

        copy_action = QAction('Copy', self)
        copy_action.setShortcut('Ctrl+C')

        cut_action = QAction('Cut', self)
        cut_action.setShortcut('Ctrl+X')

        paste_action = QAction('Paste', self)
        paste_action.setShortcut('Ctrl+V')

        minimize_action = QAction('Minimize', self)
        minimize_action.setShortcut('Ctrl+M')

        view_action = QAction('Show', self)
        view_action.setShortcut('Ctrl+/')

        menubar = self.menuBar()
        file_menu = menubar.addMenu('&File')
        edit_menu = menubar.addMenu('&Edit')
        view_menu = menubar.addMenu('&View')
        window_menu = menubar.addMenu('&Window')

        file_menu.addAction(new_action)
        file_menu.addAction(open_action)
        file_menu.addAction(save_action)
        file_menu.addAction(new_save_action)
        file_menu.addAction(close_action)
        file_menu.addAction(exit_action)

        edit_menu.addAction(undo_action)
        edit_menu.addAction(copy_action)
        edit_menu.addAction(cut_action)
        edit_menu.addAction(paste_action)

        view_menu.addAction(view_action)

        window_menu.addAction(minimize_action)

    def closeTab(self, currentIndex):
        currentQWidget = self.tabs.currentWidget()
        currentQWidget.deleteLater()
        self.tabs.removeTab(currentIndex)

    def new_file(self):
        newfile = QTextEdit()
        i = self.tabs.addTab(newfile, 'New Document')
        self.tabs.setCurrentIndex(i)

    def save_file(self):
        editor = self.tabs.currentWidget()
        filename = self.tabs.tabText(self.tabs.currentIndex())
        if filename != 'New Document':
            f = open(filename, 'w')
            filedata = editor.toPlainText()
            f.write(filedata)
            f.close()
        else:
            self.save_file_as()

    def save_file_as(self):
        filename = QFileDialog.getSaveFileName(
            self, 'Save File', os.getenv('HOME'))[0]
        print(filename)
        if filename != ('', ''):
            f = open(filename, 'w')
            filedata = self.text.toPlainText()
            f.write(filedata)
            f.close()

    def open_file(self):
        filename = QFileDialog.getOpenFileName(
            self, 'Open File', os.getenv('HOME'))[0]
        f = open(filename, 'r')
        filedata = f.read()
        f.close()
        newfile = QTextEdit()
        newfile.setText(filedata)
        i = self.tabs.addTab(newfile, filename)
        self.tabs.setCurrentIndex(i)

    def close_file(self):
        self.save_file()
        currentIndex = self.tabs.currentIndex()
        self.tabs.removeTab(currentIndex)