示例#1
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.setWindowTitle("Pomodoro")
        # all time here in seconds, in comments are default values
        self.study_time = 1500  # 1500 is 25 minutes
        self.short_break_time = 300  # 300 is 5 minutes
        self.long_break_time = 900  # 900 is 15 minutes
        self.remaining_seconds = self.study_time

        self.beep_noise = "bugle_tune.wav"  # sound played
        self.last_countdown = ""

        self.history = {}
        self.studies_today = self.load_history()
        self.last_countdown = "study"

        self.setup_settings()
        self.setup_timer()
        self.ui.button.clicked.connect(self.start_timer)
        self.ui.actionSettings.triggered.connect(self.open_settings_window)
        self.ui.pushButton.clicked.connect(self.open_calendar_window)
示例#2
0
class MyForm(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.test_btn.clicked.connect(self.btn_clicked)
    def btn_clicked(self):
        QtWidgets.QMessageBox.critical(self,"dshfs","fadsfasd")
示例#3
0
    def __init__(self, app_main):

        # Create main window UI

        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.app_main = app_main

        self.asyncCmd = None
        self.asyncCmdRunning = False

        # Create helper objects to manage main window tabs
        self.daqTab = LpdFemGuiMainDaqTab(app_main, self)
        self.pwrTab = LpdFemGuiMainPowerTab(app_main, self)
        self.configTab = LpdFemGuiMainConfigTab(app_main, self)
        self.evrTab = LpdFemGuiMainEvrTab(app_main, self)
        self.testTab = LpdFemGuiMainTestTab(app_main, self)
        self.ui.operatorEdit.text()

        if (self.app_main.asic_testing_enabled):
            pass
        else:
            # ASIC testing disabled, remove test tab
            testIdx = self.ui.verticalTabWidget.indexOf(self.ui.testTab)
            self.ui.verticalTabWidget.removeTab(testIdx)

        # Initialise default fields based on app_main object
        self.ui.connectAddr.setText(self.app_main.getCachedParam('femAddr'))
        self.ui.connectPort.setText(
            str(self.app_main.getCachedParam('femPort')))

        # Create a status bar with a progress bar
        self.createStatusBar("Not connected")

        # Connect signals and slots
        QtCore.QObject.connect(self.ui.connectButton,
                               QtCore.SIGNAL("clicked()"),
                               self.deviceConnectToggle)
        self.connect(self.ui.actionQuit, QtCore.SIGNAL('triggered()'),
                     self.quitApplication)

        # Connect msgRecv function to message signal to allow other non-GUI threads to print messages
        self.messageSignal.connect(self.msgRecv)

        # Connect runStateUpdate function to signal to allow other non-GUI threads to push state updates
        self.runStateSignal.connect(self.runStateUpdate)

        # Connect run status update function to signal to data recevier to push updates
        self.run_status_signal.connect(self.daqTab.runStatusUpdate)

        # Connect power status update function to signal
        self.powerStatusSignal.connect(self.pwrTab.powerStatusUpdateDisplay)
示例#4
0
    def __init__(self, gui_manager):
        QMainWindow.__init__(self, None)    #Initialize myself as a widget
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)    #Create the components of the window
        
        self.gui_manager = gui_manager
        
        self.dock_full_screen = False
        self.min_doc_dock_width = 200
        
        #Maximize the display to full size
        #self.showMaximized()

        #Add status bar at bottom of window
        self.statusbar = QtGui.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)
        
        #Add progress bar to status bar
        self.pb = QProgressBar(self.statusBar())
        self.pb.setMinimum(0)
        self.pb.setMaximum(0)
        self.statusbar.addPermanentWidget(self.pb)        
        self.pb.hide()
        
        QObject.connect(self.ui.menu_dock_visible, SIGNAL("triggered()"), self.toggle_documentation_window)
        QObject.connect(self.ui.dock_doc, SIGNAL("visibilityChanged(bool)"), self.toggle_dock_visible_menu)

        QObject.connect(self.ui.menu_dock_floating, SIGNAL("triggered()"), self.toggle_dock_float)
        QObject.connect(self.ui.dock_doc, SIGNAL("topLevelChanged(bool)"), self.toggle_dock_floating_menu)

        QObject.connect(self.ui.menu_open_full_doc, SIGNAL("triggered()"), self.load_full_doc)
示例#5
0
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.addToolBar(NavigationToolbar2QT(self.ui.MplWidget.canvas, self), )
        self.ui.log_scaling_checkbox.setCheckState(QtCore.Qt.Unchecked)

        self.num_decimals = 4
        self.limiting_exponent = 4

        self.wavelength_axis = 'rows'
        self.time_axis = 'columns'  # This should be adjustable outside the code to handle various types of data

        self.rows_values = 0  # the intention is that the values for "time" are in row 0 and wl are in column 0
        self.columns_values = 0  # These might be stupid names and unnecessary in general

        self.plot_full = dict(Left=False, Right=False, Lower=False)
示例#6
0
    def __init__(self,MainWindow):
        Ui_MainWindow.__init__(self)
        self.setupUi(MainWindow)
        self.alarm_stat=100

        # keeping track of connection status
        self.xx = 0

        #socket for connection
        self.s = socket.socket()
        _thread.start_new_thread(self.connection,())
        self.screenshot.clicked.connect(self.screenie)
        self.alarm.clicked.connect(self.alarmthread)
        self.webcam.clicked.connect(self.webcam_stream_thread)
        self.loc.clicked.connect(self.geoloc)
        self.notify.clicked.connect(self.message)
        time.sleep(2)
        self.settext("connection")
示例#7
0
    def __init__(self):
        super().__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # NOTE: методом подбора получились эти значения
        self.ui.splitter_main.setSizes([80, 500])

        self.setWindowTitle('Client http://readmanga.me')

        self.ui.line_edit_search.textEdited.connect(self.on_manga_search)
        self.ui.list_widget_search_result.itemDoubleClicked.connect(
            self.on_search_item_double_clicked)

        self.ui.push_button_next_page.clicked.connect(self.next_page)
        self.ui.push_button_prev_page.clicked.connect(self.prev_page)

        self.ui.combo_box_manga_chapters.currentIndexChanged.connect(
            self.on_manga_chapters_current_index_changed)
        self.ui.combo_box_pages.currentIndexChanged.connect(
            self.set_chapter_page)

        self.url_images_chapter = list()

        # Кэш страниц манги, чтобы не качать их каждый раз при смене страницы на просмотренную в главе
        self.cache_page_chapter_by_image = dict()

        self.last_item_chapter = None
        self.last_page_number = -1

        self.image_viewer = ImageViewer()
        self.ui.scroll_area_image_page.setWidget(self.image_viewer)

        self.ui.scroll_area_image_page.setWidgetResizable(True)
        self.ui.scroll_area_image_page.installEventFilter(self)

        self.download_progress_bar = QProgressBar()
        self.download_progress_bar.hide()
        self.ui.statusbar.addPermanentWidget(self.download_progress_bar)

        self._update_states()
示例#8
0
class MainWindow(QtWidgets.QMainWindow):
    """
    The main editor window.
    """

    def __init__(self):
        
        super(MainWindow, self).__init__()
        
        self._scrapExtracter = ScrapExtracter()
        self._highlight = highlight_chunks
        
        # set up UI using generated code from designer file
        self._ui = Ui_MainWindow()
        self._ui.setupUi(self)
        
        # called on every change to the text document
        self._ui.textEdit.document().contentsChange.connect(self._update_tree)
        
        # handle save button click
        self._ui.actionSave.triggered.connect(self._save)
        
    def _update_tree(self, position, charsRemoved, charsAdded):
        """
        Sync text in the document with the parse tree.
        """
        self._scraps = self._scrapExtracter.extract_scraps(
            self._ui.textEdit.toPlainText())
        self._update_document()
        
    def _update_document(self):
        """
        Update the document to reflect the parse tree.
        """
        self._highlight(self._ui.textEdit, self._scraps,
                        YellowBackground())
    
    def _save(self):
        pass
示例#9
0
    def __init__(self, gui_manager):
        QMainWindow.__init__(self, None)  #Initialize myself as a widget
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)  #Create the components of the window

        self.gui_manager = gui_manager

        self.dock_full_screen = False
        self.min_doc_dock_width = 200

        #Maximize the display to full size
        #self.showMaximized()

        #Add status bar at bottom of window
        self.statusbar = QtGui.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        #Add progress bar to status bar
        self.pb = QProgressBar(self.statusBar())
        self.pb.setMinimum(0)
        self.pb.setMaximum(0)
        self.statusbar.addPermanentWidget(self.pb)
        self.pb.hide()

        QObject.connect(self.ui.menu_dock_visible, SIGNAL("triggered()"),
                        self.toggle_documentation_window)
        QObject.connect(self.ui.dock_doc, SIGNAL("visibilityChanged(bool)"),
                        self.toggle_dock_visible_menu)

        QObject.connect(self.ui.menu_dock_floating, SIGNAL("triggered()"),
                        self.toggle_dock_float)
        QObject.connect(self.ui.dock_doc, SIGNAL("topLevelChanged(bool)"),
                        self.toggle_dock_floating_menu)

        QObject.connect(self.ui.menu_open_full_doc, SIGNAL("triggered()"),
                        self.load_full_doc)
示例#10
0
 def __init__(self):
     
     super(MainWindow, self).__init__()
     
     self._scrapExtracter = ScrapExtracter()
     self._highlight = highlight_chunks
     
     # set up UI using generated code from designer file
     self._ui = Ui_MainWindow()
     self._ui.setupUi(self)
     
     # called on every change to the text document
     self._ui.textEdit.document().contentsChange.connect(self._update_tree)
     
     # handle save button click
     self._ui.actionSave.triggered.connect(self._save)
示例#11
0
 def __init__(self, parent=None):
     QtWidgets.QWidget.__init__(self, parent)
     self.ui = Ui_MainWindow()
     self.ui.setupUi(self)
     self.ui.test_btn.clicked.connect(self.btn_clicked)
示例#12
0
class DelphosWindow(QMainWindow):
    """Manages the main Delphos window interface (Ui_MainWindow)
    """
    def __init__(self, gui_manager):
        QMainWindow.__init__(self, None)  #Initialize myself as a widget
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)  #Create the components of the window

        self.gui_manager = gui_manager

        self.dock_full_screen = False
        self.min_doc_dock_width = 200

        #Maximize the display to full size
        #self.showMaximized()

        #Add status bar at bottom of window
        self.statusbar = QtGui.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        #Add progress bar to status bar
        self.pb = QProgressBar(self.statusBar())
        self.pb.setMinimum(0)
        self.pb.setMaximum(0)
        self.statusbar.addPermanentWidget(self.pb)
        self.pb.hide()

        QObject.connect(self.ui.menu_dock_visible, SIGNAL("triggered()"),
                        self.toggle_documentation_window)
        QObject.connect(self.ui.dock_doc, SIGNAL("visibilityChanged(bool)"),
                        self.toggle_dock_visible_menu)

        QObject.connect(self.ui.menu_dock_floating, SIGNAL("triggered()"),
                        self.toggle_dock_float)
        QObject.connect(self.ui.dock_doc, SIGNAL("topLevelChanged(bool)"),
                        self.toggle_dock_floating_menu)

        QObject.connect(self.ui.menu_open_full_doc, SIGNAL("triggered()"),
                        self.load_full_doc)

        #self.ui.dock_doc.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    def load_full_doc(self, project_type=None, language=None):
        """Load full documentation in external application
        """
        #Find which documentation subdir to look in
        if not project_type:
            project_type = self.gui_manager.project_manager.get_current_project_type(
            )
        if not language:
            language = self.gui_manager.config_manager.get_language()

        if project_type == 'fisheries':
            if language == 'english':
                doc_subdir = 'fisheries' + os.sep + 'english' + os.sep
            else:
                doc_subdir = 'fisheries' + os.sep + 'spanish' + os.sep
        elif project_type == 'sites':
            if language == 'english':
                doc_subdir = 'sites' + os.sep + 'english' + os.sep
            else:
                doc_subdir = 'sites' + os.sep + 'spanish' + os.sep
        elif project_type == 'communities':
            if language == 'english':
                doc_subdir = 'communities' + os.sep + 'english' + os.sep
            else:
                doc_subdir = 'communities' + os.sep + 'spanish' + os.sep

        doc_path = os.getcwd(
        ) + os.sep + "documentation" + os.sep + doc_subdir + 'documentation.html'
        doc_url = "file:" + urllib.pathname2url(unicode(doc_path))

        #file:///U|/dev/delphos/src/documentation/fisheries/english/letter_to_experts.doc
        self.gui_manager.desktop_services.openUrl(QUrl(doc_url))

    def load_toc(self, project_type=None, language=None):
        """Loads the table of contents within the dock widget
        """
        #Find which toc data to load
        if not project_type:
            project_type = self.gui_manager.project_manager.get_current_project_type(
            )
        if not language:
            language = self.gui_manager.config_manager.get_language()

        toc = ""
        if project_type == 'fisheries':
            if language == 'english':
                toc = fisheries_english_toc
            else:
                toc = fisheries_spanish_toc
        elif project_type == 'communities':
            if language == 'english':
                toc = communities_english_toc
            else:
                toc = communities_spanish_toc
        elif project_type == 'sites':
            if language == 'english':
                toc = sites_english_toc
            else:
                toc = sites_spanish_toc
        self.process_toc(deepcopy(toc))

    def process_toc(self, toc):
        self.ui.toc_tree.clear()
        #Make a copy as original will be destroyed
        for heading in toc:
            root_item = self.ui.toc_tree.invisibleRootItem()
            self.process_heading(heading, root_item)

    def process_heading(self, heading, parent):
        #print type(heading)
        if type(heading) == str:
            tree_item = QTreeWidgetItem(parent)
            tree_item.setText(0, heading)
        if type(heading) == dict:
            (heading_name, subheadings) = heading.popitem()
            tree_item = QTreeWidgetItem(parent)
            tree_item.setText(0, heading_name)
            for subheading in subheadings:
                self.process_heading(subheading, tree_item)

    def process_toc_click(self, item, column):
        """Builds URL from toc heading name and reloads doc editor
        """
        heading = item.text(column)
        #Morph heading name into anchor label name
        label = heading.replace(' ', '_')
        label = heading.replace('/', '_')
        label = heading.replace('.', '')
        label = label.toLower()

        #Build URL
        project_type = self.gui_manager.project_manager.get_current_project_type(
        )
        language = self.gui_manager.config_manager.get_language()
        #Load URL and go to anchor within it
        self.ui.doc_browser.load_anchor(label, project_type, language)

    def process_help_click(self, en_name, sp_name):
        """Uses the help type given to load a section of the documentation
        """
        en_label = en_name.replace('help_', '')
        sp_label = sp_name.replace('help_', '')

        #Build URL
        project_type = self.gui_manager.project_manager.get_current_project_type(
        )
        language = self.gui_manager.config_manager.get_language()
        #Load URL and go to anchor within it
        if language == 'english':
            self.ui.doc_browser.load_anchor(en_label, project_type, language)
        elif language == 'spanish':
            self.ui.doc_browser.load_anchor(sp_label, project_type, language)

        #Show the documentation if its hidden
        if not self.ui.dock_doc.isVisible():
            self.ui.menu_dock_visible.trigger()

    def dock_full_screen(self):
        return self.dock_full_screen

    def toggle_dock(self):
        if self.dock_full_screen:

            self.ui.dock_doc.setMinimumSize(self.min_doc_dock_width, 0)
            self.ui.dock_doc.resize(self.min_doc_dock_width,
                                    self.ui.dock_doc.height())

            doc_dock_size = self.ui.dock_doc.sizeHint()

            self.ui.toc_box.resize(100, self.ui.toc_box.height())
            self.ui.toc_tree.resize(100, self.ui.toc_box.height())
            self.ui.doc_box.resize(100, self.ui.doc_box.height())
            self.ui.doc_browser.resize(100, self.ui.toc_box.height())
            self.dock_full_screen = False
        else:
            self.ui.dock_doc.setMinimumSize(self.width(), 0)
            self.dock_full_screen = True

    def toggle_documentation_window(self):
        if self.ui.dock_doc.isVisible():
            self.ui.dock_doc.hide()
        else:
            self.ui.dock_doc.show()

    def toggle_dock_visible_menu(self):
        if self.ui.dock_doc.isVisible():
            self.ui.menu_dock_visible.setChecked(True)
        else:
            self.ui.menu_dock_visible.setChecked(False)

    def toggle_dock_float(self):
        if self.ui.dock_doc.isFloating():
            self.ui.dock_doc.setFloating(False)
        else:
            self.ui.dock_doc.setFloating(True)

    def toggle_dock_floating_menu(self, isFloating):
        if isFloating:
            self.ui.menu_dock_floating.setChecked(False)
        else:
            self.ui.menu_dock_floating.setChecked(True)
示例#13
0
 def __init__(self):
     QMainWindow.__init__(self)
     self.ui = Ui_MainWindow()
     self.ui.setupUi(self)
     self.ui.mdiArea.setOption(QMdiArea.DontMaximizeSubWindowOnActivation, True)
示例#14
0
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.addToolBar(NavigationToolbar2QT(self.ui.MplWidget.canvas, self), )
        self.ui.log_scaling_checkbox.setCheckState(QtCore.Qt.Unchecked)

        self.num_decimals = 4
        self.limiting_exponent = 4

        self.wavelength_axis = 'rows'
        self.time_axis = 'columns'  # This should be adjustable outside the code to handle various types of data

        self.rows_values = 0  # the intention is that the values for "time" are in row 0 and wl are in column 0
        self.columns_values = 0  # These might be stupid names and unnecessary in general

        self.plot_full = dict(Left=False, Right=False, Lower=False)

    @QtCore.pyqtSlot(int)
    def log_scaling_cb_state_changed(self, state):
        if state == 2:
            prefs.scaling = 'log'
        elif state == 0:
            prefs.scaling = 'linear'

        if self.plot_full['Left']:
            self.ui.MplWidget.canvas.axes_left.set_yscale(prefs.scaling)
        if self.plot_full['Right']:
            self.ui.MplWidget.canvas.axes_right.set_yscale(prefs.scaling)
        if self.plot_full['Lower']:
            self.ui.MplWidget.canvas.axes_lower.set_yscale(prefs.scaling)
        if self.plot_full['Left'] or self.plot_full['Right'] or self.plot_full[
                'Lower']:
            self.ui.MplWidget.canvas.draw()

    @QtCore.pyqtSlot()
    def load_btn_clicked(self):
        load_file_name, _ = QFileDialog.getOpenFileName(self, 'Load File')

        # If the user doesn't cancel
        if load_file_name != '':
            data_frame = pd.read_csv(load_file_name,
                                     delimiter='\t',
                                     header=None)

            full_contents = data_frame.to_numpy()
            row_ct, col_ct = full_contents.shape
            self.times = full_contents[0, 1:col_ct]
            self.wavelengths = full_contents[1:row_ct, 0]
            data = full_contents[1:row_ct, 1:col_ct]
            self.data_values = np.transpose(data)

            self.ui.MplWidget.canvas.axes_right.clear()
            self.ui.MplWidget.canvas.axes_lower.clear()
            self.update_surf_plot(x=self.wavelengths,
                                  y=self.times,
                                  z=self.data_values,
                                  side='Left')

    def help_btn_clicked(self):
        print(
            'Does nothing at this time, see read-me file for some information')

    @QtCore.pyqtSlot()
    def clear_btn_clicked(self):
        self.ui.MplWidget.canvas.axes_left.clear()
        self.ui.MplWidget.canvas.axes_right.clear()
        self.ui.MplWidget.canvas.axes_lower.clear()

    @QtCore.pyqtSlot()
    def fit_btn_clicked(self):
        self.OpenFitWindow = FitWindow()
        self.OpenFitWindow.show()

    @QtCore.pyqtSlot()
    def prefs_btn_clicked(self):
        self.PrefsWindow = PreferencesWindow()
        self.PrefsWindow.show()

    def update_surf_plot(self,
                         x=None,
                         y=None,
                         z=None,
                         pad_axes=True,
                         side='Left'):  # , clear=False, label=None):
        if pad_axes is True:
            x_ct = len(x)
            y_ct = len(y)
            delta_x = x[x_ct - 1] - x[x_ct - 2]
            delta_y = y[y_ct - 1] - y[y_ct - 2]
            x = np.append(x, (x[x_ct - 1] + delta_x))
            y = np.append(y, (y[y_ct - 1] + delta_y))

        divnorm = colors.DivergingNorm(vcenter=0)
        if side == 'Left':
            self.ui.MplWidget.canvas.axes_left.clear()
            self.ui.MplWidget.canvas.axes_left.pcolormesh(x,
                                                          y,
                                                          z,
                                                          norm=divnorm,
                                                          cmap='bwr')
            if prefs.scaling == 'log':
                self.ui.MplWidget.canvas.axes_left.set_yscale('log')

        elif side == 'Right':
            self.ui.MplWidget.canvas.axes_right.clear()
            self.ui.MplWidget.canvas.axes_right.pcolormesh(x,
                                                           y,
                                                           z,
                                                           norm=divnorm,
                                                           cmap='bwr')
            if prefs.scaling == 'log':
                self.ui.MplWidget.canvas.axes_right.set_yscale('log')

        elif side == 'Lower':
            self.ui.MplWidget.canvas.axes_lower.clear()
            self.ui.MplWidget.canvas.axes_lower.pcolormesh(x,
                                                           y,
                                                           z,
                                                           norm=divnorm,
                                                           cmap='bwr')
            if prefs.scaling == 'log':
                self.ui.MplWidget.canvas.axes_left.set_yscale('log')

        print('side: ' + side)
        self.plot_full[side] = True
        print('plot_full: ' + str(self.plot_full))
        self.ui.MplWidget.canvas.draw()
示例#15
0
class MainWindow(QMainWindow):
    ROLE_MANGA_OBJ = Qt.UserRole
    ROLE_MANGA_URL = Qt.UserRole + 1
    ROLE_MANGA_TITLE = Qt.UserRole + 2

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

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # NOTE: методом подбора получились эти значения
        self.ui.splitter_main.setSizes([80, 500])

        self.setWindowTitle('Client http://readmanga.me')

        self.ui.line_edit_search.textEdited.connect(self.on_manga_search)
        self.ui.list_widget_search_result.itemDoubleClicked.connect(
            self.on_search_item_double_clicked)

        self.ui.push_button_next_page.clicked.connect(self.next_page)
        self.ui.push_button_prev_page.clicked.connect(self.prev_page)

        self.ui.combo_box_manga_chapters.currentIndexChanged.connect(
            self.on_manga_chapters_current_index_changed)
        self.ui.combo_box_pages.currentIndexChanged.connect(
            self.set_chapter_page)

        self.url_images_chapter = list()

        # Кэш страниц манги, чтобы не качать их каждый раз при смене страницы на просмотренную в главе
        self.cache_page_chapter_by_image = dict()

        self.last_item_chapter = None
        self.last_page_number = -1

        self.image_viewer = ImageViewer()
        self.ui.scroll_area_image_page.setWidget(self.image_viewer)

        self.ui.scroll_area_image_page.setWidgetResizable(True)
        self.ui.scroll_area_image_page.installEventFilter(self)

        self.download_progress_bar = QProgressBar()
        self.download_progress_bar.hide()
        self.ui.statusbar.addPermanentWidget(self.download_progress_bar)

        self._update_states()

    def _clear_states(self):
        self.last_page_number = -1
        self.last_item_chapter = None
        self.url_images_chapter.clear()
        self.cache_page_chapter_by_image.clear()
        self.ui.combo_box_manga_chapters.clear()
        self.ui.combo_box_pages.clear()
        self.image_viewer.clear()
        self._update_states()

    def _update_states(self):
        pages = self.ui.combo_box_pages.count()
        current_page = self.ui.combo_box_pages.currentIndex()

        self.ui.push_button_next_page.setEnabled(current_page < pages - 1)
        self.ui.push_button_prev_page.setEnabled(current_page > 0)

    def on_manga_search(self, query_text):
        self.ui.list_widget_search_result.clear()

        manga_list = search_manga_on_readmanga(query_text)

        for manga_obj in manga_list:
            data = manga_obj['data']

            # Думаю, у любой манги найдется автор, иначе игнорируем
            if 'authors' not in data:
                continue

            text = manga_obj['value']

            another_names = data['names']
            if another_names:
                text += " | " + ', '.join(another_names)

            authors = data['authors']
            if authors:
                text += " (" + authors + ")"

            url = data['link']

            item = QListWidgetItem(text)
            item.setData(self.ROLE_MANGA_OBJ, manga_obj)
            item.setData(self.ROLE_MANGA_URL, url)
            item.setData(self.ROLE_MANGA_TITLE, text)

            self.ui.list_widget_search_result.addItem(item)

    def next_page(self):
        current_index = self.ui.combo_box_pages.currentIndex()

        if current_index < self.ui.combo_box_pages.maxCount():
            self.ui.combo_box_pages.setCurrentIndex(current_index + 1)

        self._update_states()

    def prev_page(self):
        current_index = self.ui.combo_box_pages.currentIndex()

        if current_index > 0:
            self.ui.combo_box_pages.setCurrentIndex(current_index - 1)

        self._update_states()

    def on_manga_chapters_current_index_changed(self, index):
        if not self.ui.combo_box_manga_chapters.count():
            return

        url = self.ui.combo_box_manga_chapters.itemData(index)
        self.fill_chapter_viewer(url)

    def on_search_item_double_clicked(self, item):
        # Чтобы нельзя было выбрать повторно мангу
        if item == self.last_item_chapter:
            return

        self.last_item_chapter = item

        self._clear_states()

        url = item.data(self.ROLE_MANGA_URL)
        title = item.data(self.ROLE_MANGA_TITLE)

        content_as_bytes = self._download_by_url(url)

        from bs4 import BeautifulSoup
        root = BeautifulSoup(content_as_bytes, 'lxml')

        description = root.select_one('.manga-description')
        if not description:
            QMessageBox.information(self, "Внимание",
                                    "Похоже у манги нет описания")
            return

        description = description.text.strip()

        # Удаление множества подряд идущих пробелов
        import re
        description = re.sub(r'\s{2,}', ' ', description)

        self.ui.label_manga_name.setText(title)
        self.ui.text_edit_description.setText(description)

        url_first_chapter = root.select_one('.read-first > a[href]')
        if not url_first_chapter:
            QMessageBox.information(self, "Внимание",
                                    "Похоже у манги нет глав")
            return

        url_first_chapter = url_first_chapter['href']

        from urllib.parse import urljoin
        url_first_chapter = urljoin(url, url_first_chapter)

        self.fill_chapter_viewer(url_first_chapter)

    def fill_chapter_viewer(self, url_chapter):
        self._clear_states()

        # Загрузка первой главы для получения списка глав и показа первой страницы главы
        content_as_bytes = self._download_by_url(url_chapter)

        from bs4 import BeautifulSoup
        root = BeautifulSoup(content_as_bytes, 'lxml')

        from urllib.parse import urljoin
        chapter_list = [
            (option.text.strip(), urljoin(url_chapter, option['value']))
            for option in root.select('#chapterSelectorSelect > option')
        ]

        # Чтобы напрасно не вызывался сигнал currentIndexChanged при настройке комбобокса
        self.ui.combo_box_manga_chapters.blockSignals(True)

        # Заполнение списка глав
        for title_chapter, _url_chapter in chapter_list:
            self.ui.combo_box_manga_chapters.addItem(title_chapter,
                                                     _url_chapter)

        # Выбор текущей главы в комбобоксе
        index = -1

        for i in range(self.ui.combo_box_manga_chapters.count()):
            item_url = self.ui.combo_box_manga_chapters.itemData(i)
            if item_url.startswith(url_chapter):
                index = i
                break

        self.ui.combo_box_manga_chapters.setCurrentIndex(index)
        self.ui.combo_box_manga_chapters.blockSignals(False)

        # Для получения ссылок на картинки глав:
        html = str(root)
        self.url_images_chapter = get_url_images_from_chapter(html)

        # Заполнение списка с страницами главы
        self.ui.combo_box_pages.blockSignals(True)
        for i in range(len(self.url_images_chapter)):
            self.ui.combo_box_pages.addItem(str(i + 1))

        self.ui.combo_box_pages.blockSignals(False)

        current_page = self.ui.combo_box_pages.currentIndex()
        self.set_chapter_page(current_page)

        self._update_states()

    def _download_by_url(self, url):
        import requests
        rs = requests.get(url, stream=True)

        self.download_progress_bar.show()

        if 'Content-Length' in rs.headers:
            img_size = int(rs.headers['Content-Length'])
            self.download_progress_bar.setMaximum(img_size)
        else:
            # Прогресс бар становится бесконечным
            self.download_progress_bar.setMaximum(0)

        size = 0

        byte_array_img = bytearray()

        for buf in rs.iter_content(1024):
            if buf:
                byte_array_img += buf
                size += len(buf)

                self.download_progress_bar.setValue(size)

        self.download_progress_bar.hide()

        return bytes(byte_array_img)

    def set_chapter_page(self, page_number):
        if page_number == -1 or page_number == self.last_page_number:
            return

        self.last_page_number = page_number

        if page_number not in self.cache_page_chapter_by_image:
            url_first_page = self.url_images_chapter[page_number]

            content_as_bytes = self._download_by_url(url_first_page)
            img = QImage.fromData(content_as_bytes)

            self.cache_page_chapter_by_image[page_number] = img

        else:
            img = self.cache_page_chapter_by_image[page_number]

        self.image_viewer.set_image(img)

        # Возврат ползунка на положенное место
        self.ui.scroll_area_image_page.verticalScrollBar().setValue(0)

        self._update_states()

    def eventFilter(self, obj, event):
        # Для изменения ширины картинки
        if obj == self.ui.scroll_area_image_page and event.type(
        ) == QEvent.Resize:
            # Чтобы был небольшой отступ по краям
            margin = 40
            self.image_viewer.setFixedWidth(
                self.ui.scroll_area_image_page.width() - margin)

        return super().eventFilter(obj, event)
示例#16
0
class MainApp(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.setWindowTitle("Pomodoro")
        # all time here in seconds, in comments are default values
        self.study_time = 1500  # 1500 is 25 minutes
        self.short_break_time = 300  # 300 is 5 minutes
        self.long_break_time = 900  # 900 is 15 minutes
        self.remaining_seconds = self.study_time

        self.beep_noise = "bugle_tune.wav"  # sound played
        self.last_countdown = ""

        self.history = {}
        self.studies_today = self.load_history()
        self.last_countdown = "study"

        self.setup_settings()
        self.setup_timer()
        self.ui.button.clicked.connect(self.start_timer)
        self.ui.actionSettings.triggered.connect(self.open_settings_window)
        self.ui.pushButton.clicked.connect(self.open_calendar_window)

    def open_settings_window(self):
        self.settings_dialog = SettingsWindow()
        self.settings_dialog.submitted.connect(self.change_times)

    def open_calendar_window(self):
        self.calendar_window = CalendarWindow(self.history)

    def setup_settings(self):
        config = ConfigParser()
        try:
            config.read("config.ini")
            self.study_time = int(config.get('main', 'study time'))
            self.short_break_time = int(config.get('main', 'short break'))
            self.long_break_time = int(config.get('main', 'long break'))
            self.remaining_seconds = int(config.get("main", 'study time'))

        except:
            config.read("config.ini")
            config.add_section("main")
            config.set("main", "study time", "1500")
            config.set("main", "short break", "300")
            config.set("main", "long break", "900")
            with open('config.ini', 'w') as f:
                config.write(f)

    def change_times(self, study_time, short_break_time, long_break_time):
        self.study_time = int(study_time)
        self.short_break_time = int(short_break_time)
        self.long_break_time = int(long_break_time)

    def setup_timer(self):
        self.ui.times_studied.setText(f"🍅 {self.studies_today} times today")

    def start_timer(self):

        self.ui.button.setText("Pause")
        self.ui.button.clicked.connect(self.pause_timer)

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.countdown)
        self.timer.start(1000)

    def pause_timer(self):
        self.timer.stop()

        self.ui.button.setText("Resume")
        self.ui.button.clicked.connect(self.start_timer)

    def countdown(self):

        if self.remaining_seconds == 0:
            self.timer.stop()
            self.ui.timer_display.setText("00:00")

            self.ui.button.setText("Start")
            self.ui.button.clicked.connect(self.start_timer)
            self.remaining_seconds = self.study_time

            if self.last_countdown == "study":
                self.studies_today += 1
                self.save_history()

                if self.studies_today % 4 == 0:
                    self.remaining_seconds = self.long_break_time
                else:
                    self.remaining_seconds = self.short_break_time
                self.last_countdown = "break"

                self.ui.times_studied.setText(
                    f"🍅 {self.studies_today} times today")

                QtMultimedia.QSound.play(self.beep_noise)

            elif self.last_countdown == "break":
                self.remaining_seconds = self.study_time
                self.last_countdown = "study"

                QtMultimedia.QSound.play(self.beep_noise)

        else:
            # countdown from 25 minutes to 0
            minutes = int(
                (self.remaining_seconds - (self.remaining_seconds % 60)) / 60)

            # displaying 0 minutes as 00:00 not as 0:00
            if minutes == 0:
                minutes = "00"
            else:
                minutes = str(minutes)

            seconds = self.remaining_seconds % 60

            # displaying 0 seconds as 00:00 not as 00:0
            if seconds == 0:
                seconds = "00"
            else:
                seconds = str(seconds)

            if len(minutes) == 1:
                minutes = "0" + minutes
            if len(seconds) == 1:
                seconds = "0" + seconds

            self.ui.timer_display.setText(f"{minutes}:{seconds}")
            self.remaining_seconds -= 1

    def load_history(self):

        try:
            with open("history.json", 'r') as file:
                self.history = json.load(file)
        except FileNotFoundError:
            with open('history.json', 'w') as file:
                json.dump(self.history, file)

        if str(date.today()) in self.history.keys():
            return int((self.history[str(date.today())]))
        else:
            return 0

    def save_history(self):

        if str(date.today()) in self.history.keys():
            self.history[str(date.today())] += 1
        else:
            self.history[str(date.today())] = 1

        with open("history.json", 'w') as file1:
            json.dump(self.history, file1)
示例#17
0
    def __init__(self):
        print('AppWindow::__init__()')
        super().__init__()
        self.settings = QSettings('./settings.ini', QSettings.IniFormat)
        self.defaultBboxesLandscape = [
            QRectF(0, 0.1, 1, 0.8),
            QRectF(0.1, 0.1, 0.9, 0.8)
        ]
        self.defaultBboxesPortrait = [
            QRectF(0, 0, 1, 0), QRectF(0.05, 0.05, 0.9, 0)
        ]

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.buttonDone.clicked.connect(self.slot_on_buttonDone_clicked)
        self.ui.buttonSwitchInOutEditor.clicked.connect(
            self.slot_on_buttonSwitchInOutEditor_clicked)
        self.ui.buttonSwapInOutEditor.clicked.connect(
            self.slot_on_buttonSwapInOutEditor_clicked)
        self.ui.buttonImageNext.clicked.connect(
            self.slot_on_buttonImageNext_clicked)
        self.ui.buttonImagePrev.clicked.connect(
            self.slot_on_buttonImagePrev_clicked)
        self.ui.buttonLoadKdenlive.clicked.connect(
            self.slot_on_buttonLoadKdenlive_clicked)
        self.ui.buttonLoadImages.clicked.connect(
            self.slot_on_buttonLoadImages_clicked)
        self.ui.buttonSaveKdenlive.clicked.connect(
            self.slot_on_buttonSaveKdenlive_clicked)
        self.ui.buttonSaveBboxesJson.clicked.connect(
            self.slot_on_buttonSaveBboxesJson_clicked)
        self.ui.buttonApplyBboxRatioMultiplier.clicked.connect(
            self.slot_on_buttonApplyBboxRatioMultiplier_clicked)
        self.ui.lineeditTargetVideoResolution.textChanged.connect(
            self.slot_on_lineeditTargetVideoResolution_textChanged)
        self.ui.checkboxStayInside.toggled.connect(
            self.slot_on_checkboxStayInside_toggled)
        self.ui.buttonLoadKdenlive.setShortcut(QKeySequence('Ctrl+o'))
        self.ui.buttonSwitchInOutEditor.setShortcut(QKeySequence('Tab'))
        self.ui.buttonSwapInOutEditor.setShortcut(QKeySequence('w'))
        self.ui.buttonImageNext.setShortcut(QKeySequence('Space'))
        self.ui.buttonImagePrev.setShortcut(QKeySequence('Backspace'))
        self.ui.checkboxStayInside.setShortcut(QKeySequence('s'))
        self.ui.buttonSaveKdenlive.setEnabled(False)
        self.ui.buttonImageNext.setEnabled(False)
        self.ui.buttonImagePrev.setEnabled(False)
        self.ui.lineeditTargetVideoResolution.setText('1920x1080')
        #		self.ui.image.setTargetRatio(1920 / 1080) # Aspect ratio of the video slideshow
        self.ui.image.bboxesChanged.connect(self.bboxesChanged)
        self.fileFormats = [
            'All supported formats: *.kdenlive, *.json (*.kdenlive *.json)',
            'Kdenlive Project Files: *.kdenlive (*.kdenlive)',
            'Bboxes Json: *.json (*.json)',
        ]
        self.kdenliveFile = None
        self.images = []
        self.imagesData = {}
        self.imageIdx = 0
        if len(sys.argv) > 1:
            if re.match('.*\.kdenlive', sys.argv[1]):
                self.LoadKdenliveFile(sys.argv[1])
            else:
                self.images = sys.argv[1:]
                print('images:', self.images)

            # Load bboxes from json
            try:
                self.LoadBboxesJson(self.getBboxesFilename())
            except:
                print('WARNING: unable to parse json data')
                traceback.print_exc()

            # Override json bboxes with kdenlive clip transformations
            if self.kdenliveFile is not None:
                self.KdenliveFileToImagesData()

            img_path = self.images[self.imageIdx]
            print('imagesData:', self.imagesData)
            self.SetImageIdx(self.imageIdx)

        self.show()
示例#18
0
class AppWindow(QMainWindow):
    def __init__(self):
        print('AppWindow::__init__()')
        super().__init__()
        self.settings = QSettings('./settings.ini', QSettings.IniFormat)
        self.defaultBboxesLandscape = [
            QRectF(0, 0.1, 1, 0.8),
            QRectF(0.1, 0.1, 0.9, 0.8)
        ]
        self.defaultBboxesPortrait = [
            QRectF(0, 0, 1, 0), QRectF(0.05, 0.05, 0.9, 0)
        ]

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.buttonDone.clicked.connect(self.slot_on_buttonDone_clicked)
        self.ui.buttonSwitchInOutEditor.clicked.connect(
            self.slot_on_buttonSwitchInOutEditor_clicked)
        self.ui.buttonSwapInOutEditor.clicked.connect(
            self.slot_on_buttonSwapInOutEditor_clicked)
        self.ui.buttonImageNext.clicked.connect(
            self.slot_on_buttonImageNext_clicked)
        self.ui.buttonImagePrev.clicked.connect(
            self.slot_on_buttonImagePrev_clicked)
        self.ui.buttonLoadKdenlive.clicked.connect(
            self.slot_on_buttonLoadKdenlive_clicked)
        self.ui.buttonLoadImages.clicked.connect(
            self.slot_on_buttonLoadImages_clicked)
        self.ui.buttonSaveKdenlive.clicked.connect(
            self.slot_on_buttonSaveKdenlive_clicked)
        self.ui.buttonSaveBboxesJson.clicked.connect(
            self.slot_on_buttonSaveBboxesJson_clicked)
        self.ui.buttonApplyBboxRatioMultiplier.clicked.connect(
            self.slot_on_buttonApplyBboxRatioMultiplier_clicked)
        self.ui.lineeditTargetVideoResolution.textChanged.connect(
            self.slot_on_lineeditTargetVideoResolution_textChanged)
        self.ui.checkboxStayInside.toggled.connect(
            self.slot_on_checkboxStayInside_toggled)
        self.ui.buttonLoadKdenlive.setShortcut(QKeySequence('Ctrl+o'))
        self.ui.buttonSwitchInOutEditor.setShortcut(QKeySequence('Tab'))
        self.ui.buttonSwapInOutEditor.setShortcut(QKeySequence('w'))
        self.ui.buttonImageNext.setShortcut(QKeySequence('Space'))
        self.ui.buttonImagePrev.setShortcut(QKeySequence('Backspace'))
        self.ui.checkboxStayInside.setShortcut(QKeySequence('s'))
        self.ui.buttonSaveKdenlive.setEnabled(False)
        self.ui.buttonImageNext.setEnabled(False)
        self.ui.buttonImagePrev.setEnabled(False)
        self.ui.lineeditTargetVideoResolution.setText('1920x1080')
        #		self.ui.image.setTargetRatio(1920 / 1080) # Aspect ratio of the video slideshow
        self.ui.image.bboxesChanged.connect(self.bboxesChanged)
        self.fileFormats = [
            'All supported formats: *.kdenlive, *.json (*.kdenlive *.json)',
            'Kdenlive Project Files: *.kdenlive (*.kdenlive)',
            'Bboxes Json: *.json (*.json)',
        ]
        self.kdenliveFile = None
        self.images = []
        self.imagesData = {}
        self.imageIdx = 0
        if len(sys.argv) > 1:
            if re.match('.*\.kdenlive', sys.argv[1]):
                self.LoadKdenliveFile(sys.argv[1])
            else:
                self.images = sys.argv[1:]
                print('images:', self.images)

            # Load bboxes from json
            try:
                self.LoadBboxesJson(self.getBboxesFilename())
            except:
                print('WARNING: unable to parse json data')
                traceback.print_exc()

            # Override json bboxes with kdenlive clip transformations
            if self.kdenliveFile is not None:
                self.KdenliveFileToImagesData()

            img_path = self.images[self.imageIdx]
            print('imagesData:', self.imagesData)
            self.SetImageIdx(self.imageIdx)

        self.show()

    def setShortcut(button, shortcutStr):
        button.setShortcut(QKeySequence(shortcutStr))
        button.setText(button.text() + ' [' + shortcutStr + ']')

    def closeEvent(self, e):
        print('closeEvent()')
        #self.save()

    def bboxesChanged(self):
        self.updateInfo()

    def updateInfo(self):
        if len(self.images) == 0:
            return
        bboxes = self.ui.image.getBboxes01()
        #print('images:', self.images)
        #print('bboxes:', bboxes)
        self.ui.labelInfoPath.setText(self.images[self.imageIdx])
        self.ui.labelInfoScale.setText(
            'in -> out scale: %02f' %
            (bboxes[1].width() /
             bboxes[0].width() if bboxes[0].width() > 0 else -1))

    def getTargetRatio(self):
        a = self.ui.lineeditTargetVideoResolution.text().split('x')
        w = int(a[0])
        h = int(a[1])
        return w / h  # Aspect ratio of the video slideshow

    def slot_on_lineeditTargetVideoResolution_textChanged(self, text):
        self.ui.image.setTargetRatio(
            self.getTargetRatio())  # Aspect ratio of the video slideshow

    def slot_on_checkboxStayInside_toggled(self, checked):
        print('toggled()', checked)
        #		print('CHECK 611 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        self.ui.image.setStayInside(checked)
        #		print('CHECK 612 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        img_path = self.images[self.imageIdx]
        #		print('CHECK 613 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        self.imagesData[img_path]['stay_inside_image'] = checked
#		print('CHECK 614 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])

    def toJson(self):
        out = {}
        for img_path in self.imagesData:
            print('img_path:', img_path)
            out[img_path] = {}
            out[img_path]['stay_inside_image'] = self.imagesData[img_path][
                'stay_inside_image'] if 'stay_inside_image' in self.imagesData[
                    img_path] else True
            out[img_path]['bboxes'] = []
            for bbox in self.imagesData[img_path]['bboxes']:
                out[img_path]['bboxes'].append({
                    'x': bbox.x(),
                    'y': bbox.y(),
                    'w': bbox.width(),
                    'h': bbox.height()
                })
        return json.dumps(out, indent=4)

    def fromJson(self, jsonStr):
        self.imagesData = {}
        jsonObj = json.loads(jsonStr)
        print('jsonObj:', jsonObj)
        for img_path in jsonObj:
            print('img_path:', img_path)
            bboxes = []
            for bbox in jsonObj[img_path]['bboxes']:
                print('bbox:', bbox)
                bboxes.append(
                    QRectF(bbox['x'], bbox['y'], bbox['w'], bbox['h']))
            self.imagesData[img_path] = {
                'stay_inside_image': jsonObj[img_path]['stay_inside_image'],
                'bboxes': bboxes
            }
            if img_path not in self.images:
                self.images.append(img_path)
        print('imagesData:', self.imagesData)

    def slot_on_buttonDone_clicked(self):
        print('clicked')
        self.close()

    def slot_on_buttonSwitchInOutEditor_clicked(self):
        print('switch editor')
        #traceback.print_stack(file = sys.stdout)
        self.ui.image.switchEditor()

    def slot_on_buttonSwapInOutEditor_clicked(self):
        print('swap editor')
        self.ui.image.swapEditors()

    def areBboxesInsideImage(self, bboxes):
        inside = True
        for bbox in bboxes:
            if bbox.left() < 0 or bbox.top() < 0 or bbox.right(
            ) > 1 or bbox.bottom() > 1:
                inside = False
            print('areBboxesInsideImage() bbox:', bbox, 'inside:', inside)
        print('areBboxesInsideImage() return ', inside)
        return inside

    def SetImageIdx(self, idx):
        print('SetImageIdx() ', self.imageIdx, '->', idx)
        #		print('CHECK 1 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])

        #print('SetImageIdx() imagesData:', self.imagesData)
        self.SaveCurrentImageData()
        #		print('CHECK 2 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])

        # Temporarily don't restrict bboxes
        self.ui.checkboxStayInside.setChecked(False)

        #		print('CHECK 3 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        self.imageIdx = max(0, min(len(self.images) - 1, idx))
        print('SetImageIdx() imageIdx:', self.imageIdx)
        img_path = self.images[self.imageIdx]
        print('SetImageIdx() img_path:', img_path)
        self.ui.image.openImage(img_path)
        #		print('CHECK 4 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        bboxes = []
        if img_path in self.imagesData:
            print('SetImageIdx() img_path:', img_path, 'bboxes:',
                  self.imagesData[img_path])
            #self.ui.checkboxStayInside.setChecked(self.imagesData[img_path]['stay_inside_image'])
            bboxes = []
            if 'bboxes' in self.imagesData[img_path]:
                bboxes = self.imagesData[img_path]['bboxes']
#		print('CHECK 5 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
        print('SetImageIdx() bboxes 1:', bboxes)

        if len(bboxes) != 2:
            print('SetImageIdx() no bboxes found -> creating default bboxes')
            bboxes = []
            img_size = self.ui.image.getImageSize()

            if img_size.width() > img_size.height():
                for bbox in self.defaultBboxesLandscape:
                    bboxes.append(QRectF(bbox))
                print('SetImageIdx() bboxes 2:', bboxes)
            else:
                ratio_img = img_size.height() / img_size.width()
                ratio_target = self.getTargetRatio()
                print('SetImageIdx() ratio_img:', ratio_img)
                for bbox in self.defaultBboxesPortrait:
                    bbox_copy = QRectF(bbox)
                    bbox_copy.setWidth(bbox_copy.width() * ratio_img *
                                       ratio_target)
                    bbox_copy.setHeight(bbox_copy.width() / ratio_img /
                                        ratio_target)
                    print('SetImageIdx() bbox_copy: ', bbox_copy)
                    bbox_copy.moveCenter(QPointF(0.5, 0.5))
                    print('SetImageIdx() bbox_copy: ', bbox_copy)
                    bboxes.append(bbox_copy)
                print('SetImageIdx() bboxes 3:', bboxes)
#		print('CHECK 6 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])

        if len(bboxes) == 2:
            print('SetImageIdx() bboxes:', bboxes)
            self.ui.image.setBboxes01(bboxes)
            #			print('CHECK 61 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
            stay_inside = self.areBboxesInsideImage(bboxes)
            print('SetImageIdx() stay_inside:', stay_inside)
            #			print('CHECK 62 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
            self.ui.checkboxStayInside.setChecked(stay_inside)
#			print('CHECK 63 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])
#		print('CHECK 7 3567_IMG.jpg bboxes: ',self.imagesData['clips/3567_IMG.jpg']['bboxes'])

        self.ui.buttonImagePrev.setEnabled(self.imageIdx > 0)
        self.ui.buttonImageNext.setEnabled(
            self.imageIdx + 1 < len(self.images))
        self.updateInfo()

    def slot_on_buttonImageNext_clicked(self):
        print('on_buttonImageNext_clicked()')
        self.SetImageIdx(self.imageIdx + 1)

    def slot_on_buttonImagePrev_clicked(self):
        print('on_buttonImagePrev_clicked()')
        self.SetImageIdx(self.imageIdx - 1)

    def LoadKdenliveFile(self, filename):
        print('LoadKdenliveFile()')
        self.kdenliveFile = KdenliveFile()
        self.kdenliveFile.Load(filename)
        self.ui.buttonSaveKdenlive.setEnabled(True)

    def KdenliveFileToImagesData(self):
        images_data = self.kdenliveFile.GetImagesData()
        images_data = dict(
            filter(lambda elem: re.match('.*\.jpg', elem[0]),
                   images_data.items()))
        for img_path in images_data:
            if img_path not in self.images:
                self.images.append(img_path)
        for img_path in images_data:
            print('img_path:', img_path)
            if 'bboxes' in images_data[img_path] and len(
                    images_data[img_path]['bboxes']) > 0:
                if img_path in self.imagesData:
                    print('overriding json bboxes:', self.imagesData[img_path],
                          ' with clip transform bboxes:',
                          images_data[img_path])
                self.imagesData[img_path] = images_data[img_path]
        self.imagesData = {**self.imagesData, **images_data}

    def LoadBboxesJson(self, filename):
        with open(filename, 'r') as f:
            json_str = f.read()
            print('json_str:', json_str)
            self.fromJson(json_str)

    def slot_on_buttonLoadKdenlive_clicked(self):
        print('slot_on_buttonLoadKdenlive_clicked()')
        #filename, filt = QFileDialog.getOpenFileName(self, "Load .kdenlive", "", "Kdenlive Project Files (*.kdenlive)")
        filename, filt = QFileDialog.getOpenFileName(
            self, "Load .kdenlive", self.settings.value('filedialog_path', ''),
            ';;'.join(self.fileFormats), self.fileFormats[0])
        if filename is None or filename == '':
            return
        self.settings.setValue('filedialog_path', os.path.dirname(filename))
        ext = os.path.splitext(filename)[1].lower()
        print('filename:', filename)
        print('filt:', filt)
        print('ext:', ext)
        if ext == '.kdenlive':
            self.LoadKdenliveFile(filename)
            self.KdenliveFileToImagesData()
        elif ext == '.json':
            self.LoadBboxesJson(filename)
        self.SetImageIdx(0)

    def LoadImages(self, filenames):
        self.images = filanemes
        self.SetImageIdx(0)

    def slot_on_buttonLoadImages_clicked(self):
        print('slot_on_buttonLoadImages_clicked()')
        filenames, filt = QFileDialog.getOpenFileNames(
            self, "Load images", self.settings.value('filedialog_path', ''),
            "Image Files (*.jpg, *.png, *.tiff)")
        if filename is None or filename == '':
            return
        self.settings.setValue('filedialog_path', os.path.dirname(filename))
        print('filenames:', filenames)
        self.LoadImages(filenames)

    def SaveKdenlive(self, filename):
        self.SaveCurrentImageData()
        if self.kdenliveFile is None:
            return
        #self.setBboxesRatioMultiplier(0.5)
        self.kdenliveFile.GroupClipsWithSameBoundaries()
        #self.kdenliveFile.AddBeats('Radioactive- Gatsby Souns live.mp3', '/media/miso/data/mp3/Dali Hornak/Radioactive- Gatsby Souns live.mp3.downbeats')
        self.kdenliveFile.AddBeatsForAllMusicClips()
        self.kdenliveFile.AddBeatGuides()
        self.kdenliveFile.SynchronizeToBeats()
        # Note: SetImagesData() has to be applied after SynchronizeToBeats() which modifies duration of clips
        self.kdenliveFile.SetImagesData(self.imagesData)
        self.kdenliveFile.Save(filename)
        self.kdenliveFile.DumpClipsLength()
        print('filename:', filename)

        # Check saved file:
        #f_saved = KdenliveFile()
        #f_saved.Load(filename)
        #print('f_saved:')
        #f_saved.DumpClipsLength()

    def slot_on_buttonSaveKdenlive_clicked(self):
        print('slot_on_buttonSaveKdenlive_clicked()')
        filename, filt = QFileDialog.getSaveFileName(
            self, "Save .kdenlive", self.settings.value('filedialog_path', ''),
            "Kdenlive Project Files (*.kdenlive)")
        if filename is None or filename == '':
            return
        self.settings.setValue('filedialog_path', os.path.dirname(filename))
        print('filename:', filename)
        self.SaveKdenlive(filename)

    def SaveBboxesJson(self, filename):
        self.SaveCurrentImageData()
        json_str = self.toJson()
        print('json_str:', json_str)
        with open(filename, "w") as text_file:
            text_file.write(json_str)

    def slot_on_buttonSaveBboxesJson_clicked(self):
        print('slot_on_buttonSaveBboxesJson_clicked()')
        filename, filt = QFileDialog.getSaveFileName(
            self, "Save bboxes .json",
            self.settings.value('filedialog_path', ''), "Bboxes json (*.json)")
        if filename is None or filename == '':
            return
        self.settings.setValue('filedialog_path', os.path.dirname(filename))
        print('filename:', filename)
        self.SaveBboxesJson(filename)

    def SaveCurrentImageData(self):
        bboxes = self.ui.image.getBboxes01()
        for bbox in bboxes:
            if bbox.isEmpty():
                return
        img_path = self.images[self.imageIdx]
        if not img_path in self.imagesData:
            self.imagesData[img_path] = {}
        self.imagesData[img_path]['bboxes'] = bboxes
        print('SaveCurrentImageData() img_path:', img_path, 'bboxes:', bboxes)

    def getBboxesFilename(self):
        if self.kdenliveFile is None:
            return 'image_bboxes.json'
        else:
            return re.sub(r'\.kdenlive', '_bboxes.json',
                          self.kdenliveFile.inputFilename)

    def setBboxesRatioMultiplier(self, ratioMultiplier):
        print('setBboxesRatioMultiplier() len:', len(self.imagesData))
        for img_path in self.imagesData:
            print('setBboxesRatioMultiplier() img_path:', img_path)
            if 'bboxes' not in self.imagesData[img_path]:
                continue
            bboxes = self.imagesData[img_path]['bboxes']
            if len(bboxes) != 2:
                continue
            bbox_small = bboxes[0]
            bbox_large = bboxes[1]
            if bbox_small.width() > bbox_large.width():
                # swap
                bbox_small, bbox_large = bbox_large, bbox_small

            print('setBboxesRatioMultiplier() bbox_small:', bbox_small)
            print('setBboxesRatioMultiplier() bbox_large:', bbox_large)
            diff_l = bbox_small.left() - bbox_large.left()
            diff_r = bbox_small.right() - bbox_large.right()
            diff_t = bbox_small.top() - bbox_large.top()
            diff_b = bbox_small.bottom() - bbox_large.bottom()
            bbox_small.setLeft(bbox_large.left() + diff_l * ratioMultiplier)
            bbox_small.setTop(bbox_large.top() + diff_t * ratioMultiplier)
            bbox_small.setRight(bbox_large.right() + diff_r * ratioMultiplier)
            bbox_small.setBottom(bbox_large.bottom() +
                                 diff_b * ratioMultiplier)
            print('setBboxesRatioMultiplier() bbox_small adjusted:',
                  bbox_small)
            print('setBboxesRatioMultiplier() bboxes:', bboxes)
        # Update view
        self.SetImageIdx(self.imageIdx)

    def slot_on_buttonApplyBboxRatioMultiplier_clicked(self):
        print('slot_on_buttonApplyBboxRatioMultiplier_clicked()')
        mul = self.ui.spinboxBboxRatioMultiplier.value()
        print('slot_on_buttonApplyBboxRatioMultiplier_clicked() mul:', mul)
        self.setBboxesRatioMultiplier(mul)
示例#19
0
    def __init__(self, parent=None):
        """Initializes the Main Window"""
        self.logger = logging.getLogger('pymetadatamanager.main_window')
        self.logger.info('Creating the main window.')
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #Create a dom representing the shows in the database
        self.shows = dbTV.make_shows_list()
        #Turn that into a model
        model = ShowListModel(self.shows)
        #Set that as the model for the listView
        self.ui.listView_shows.setModel(model)

        #Set the initial tabs to be shown
        self.ui.tabWidget_main.setCurrentIndex(0)
        self.ui.tabWidget_tv_info.setCurrentIndex(0)

        #Create a progress dialog for downloading images
        self.progress = QtGui.QProgressDialog()
        self.progress.setCancelButtonText(QtCore.QString())
        self.progress.setMinimum(0)
        self.progress.setGeometry(500, 500, 50, 100)
        self.progress.setMinimumDuration(500)
        self.progress.setWindowModality(QtCore.Qt.WindowModal)
        self.progress.setWindowTitle("Information")

        #Create a dialog window
        self.input_dialog = QtGui.QInputDialog()
        self.input_dialog.setGeometry(1000, 1000, 50, 100)
        self.input_dialog.setWindowTitle("Multiple Matches")

        #Set up the thread for saving files
        self.save_files = SaveFiles()

        # Connect sockets to slots
        self.ui.listView_shows.clicked.connect(self.list_view_clicked)
        self.ui.columnView_season_episode.clicked.connect(\
          self.column_view_clicked)
#        self.ui.combo_actors.currentIndexChanged.connect(self.set_actor_thumb)
        self.ui.lineEdit_series_name.textEdited.connect(\
          self.set_series_name_updated)
        self.ui.plainTextEdit_overview.textChanged.connect(\
          self.set_series_overview_updated)
        self.ui.lineEdit_network.textEdited.connect(\
          self.set_series_network_updated)
        self.ui.lineEdit_airtime.textEdited.connect(\
          self.set_series_airtime_updated)
        self.ui.lineEdit_runtime.textEdited.connect(\
          self.set_series_runtime_updated)
        self.ui.lineEdit_status.textEdited.connect(\
          self.set_series_status_updated)
        self.ui.pushButton_save_series_changes.pressed.connect(\
          self.update_series)
        self.ui.pushButton_revert_series_changes.pressed.connect(\
          self.revert_series)
        self.ui.pushButton_load_local_series_nfo.pressed.connect(\
          self.load_series_nfo)
        self.ui.pushButton_update_series_from_tvdb.pressed.connect(\
          self.update_series_from_tvdb)
        self.ui.line_episode_name.textEdited.connect(\
          self.set_episode_name_updated)
        self.ui.text_episode_plot.textChanged.connect(\
          self.set_episode_plot_updated)
        self.ui.line_airdate.textEdited.connect(\
          self.set_episode_airdate_updated)
        self.ui.line_tvdb_id.textEdited.connect(\
          self.set_episode_id_updated)
        self.ui.line_tvdb_rating.textEdited.connect(\
          self.set_episode_tvdb_rating_updated)
        self.ui.pushButton_save_episode_changes.pressed.connect(\
          self.update_episode)
        self.ui.pushButton_revert_episode_changes.pressed.connect(\
          self.revert_episode)
        self.ui.pushButton_load_local_episode_nfo.pressed.connect(\
          self.load_episode_nfo)
        self.ui.pushButton_update_episode_from_tvdb.pressed.connect(\
          self.update_episode_from_tvdb)
        self.ui.pushButton_new_series_poster.pressed.connect(\
          self.select_series_poster)
        self.ui.pushButton_new_series_wide_banner.pressed.connect(\
          self.select_series_wide_banner)
        self.ui.pushButton_new_season_poster.pressed.connect(\
          self.select_season_poster)
        self.ui.pushButton_new_season_wide.pressed.connect(\
          self.select_season_wide_banner)
        self.ui.pushButton_new_series_fanart.pressed.connect(\
          self.select_series_fanart)
        self.ui.actionScan_Files.triggered.connect(\
          self.scan_files)
        self.ui.actionEdit_Preferences.triggered.connect(\
          self.edit_preferences)
        self.ui.actionClear_Cache.triggered.connect(\
          self.clear_cache)
        self.ui.actionSave_all.triggered.connect(\
          self.save_all)
        self.ui.actionSave_series_artwork.triggered.connect(\
          self.save_series_artwork)
        self.ui.actionSave_series_nfo.triggered.connect(\
          self.save_series_nfo)
        self.ui.actionSave_series_both.triggered.connect(\
          self.save_series_both)
        self.ui.actionSave_episode_artwork.triggered.connect(\
          self.save_episode_artwork)
        self.ui.actionSave_episode_nfo.triggered.connect(\
          self.save_episode_nfo)
        self.ui.actionSave_episode_both.triggered.connect(\
          self.save_episode_both)
        self.save_files.started.connect(self.started_status)
        self.save_files.finished.connect(self.finished_status)
        self.save_files.terminated.connect(self.terminated_status)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("updateStatus(QString)"), \
                     self.update_status)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("updateProgress(int)"), \
                     self.update_progress)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("setupProgress(int)"), \
                     self.setup_progress)

        #Initialize some variables
        self.series_name_updated = 0
        self.series_overview_updated = 0
        self.series_network_updated = 0
        self.series_airtime_updated = 0
        self.series_runtime_updated = 0
        self.series_status_updated = 0
        self.episode_name_updated = 0
        self.episode_plot_updated = 0
        self.episode_airdate_updated = 0
        self.episode_tvdb_rating_updated = 0

        #Create some empty lists for later
        self.series_banners_url = []
        self.series_banners_wide_url = []
        self.series_fanart_banners_url = []
        self.season_banners_url = []
        self.season_banners_wide_url = []

        #Initialize the configuration dialog
        self.config_dialog = ConfigDialog()
        self.config_dialog.accepted.connect(self.read_config)
        
        self.ui.pushButton_save_series_changes.setEnabled(0)
        self.ui.pushButton_revert_series_changes.setEnabled(0)
        self.ui.pushButton_save_episode_changes.setEnabled(0)
        self.ui.pushButton_revert_episode_changes.setEnabled(0)
        self.ui.pushButton_new_series_poster.setEnabled(0)
        self.ui.pushButton_new_series_wide_banner.setEnabled(0)
        self.ui.pushButton_new_season_poster.setEnabled(0)
        self.ui.pushButton_new_season_wide.setEnabled(0)
        self.ui.pushButton_load_local_series_nfo.setEnabled(0)
        self.ui.pushButton_load_local_episode_nfo.setEnabled(0)
        self.ui.pushButton_update_series_from_tvdb.setEnabled(0)
        self.ui.pushButton_update_episode_from_tvdb.setEnabled(0)

        #Put a progress bar on the status bar
        self.pb = QtGui.QProgressBar()
        self.statusBar().addPermanentWidget(self.pb)
示例#20
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        """Initializes the Main Window"""
        self.logger = logging.getLogger('pymetadatamanager.main_window')
        self.logger.info('Creating the main window.')
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #Create a dom representing the shows in the database
        self.shows = dbTV.make_shows_list()
        #Turn that into a model
        model = ShowListModel(self.shows)
        #Set that as the model for the listView
        self.ui.listView_shows.setModel(model)

        #Set the initial tabs to be shown
        self.ui.tabWidget_main.setCurrentIndex(0)
        self.ui.tabWidget_tv_info.setCurrentIndex(0)

        #Create a progress dialog for downloading images
        self.progress = QtGui.QProgressDialog()
        self.progress.setCancelButtonText(QtCore.QString())
        self.progress.setMinimum(0)
        self.progress.setGeometry(500, 500, 50, 100)
        self.progress.setMinimumDuration(500)
        self.progress.setWindowModality(QtCore.Qt.WindowModal)
        self.progress.setWindowTitle("Information")

        #Create a dialog window
        self.input_dialog = QtGui.QInputDialog()
        self.input_dialog.setGeometry(1000, 1000, 50, 100)
        self.input_dialog.setWindowTitle("Multiple Matches")

        #Set up the thread for saving files
        self.save_files = SaveFiles()

        # Connect sockets to slots
        self.ui.listView_shows.clicked.connect(self.list_view_clicked)
        self.ui.columnView_season_episode.clicked.connect(\
          self.column_view_clicked)
#        self.ui.combo_actors.currentIndexChanged.connect(self.set_actor_thumb)
        self.ui.lineEdit_series_name.textEdited.connect(\
          self.set_series_name_updated)
        self.ui.plainTextEdit_overview.textChanged.connect(\
          self.set_series_overview_updated)
        self.ui.lineEdit_network.textEdited.connect(\
          self.set_series_network_updated)
        self.ui.lineEdit_airtime.textEdited.connect(\
          self.set_series_airtime_updated)
        self.ui.lineEdit_runtime.textEdited.connect(\
          self.set_series_runtime_updated)
        self.ui.lineEdit_status.textEdited.connect(\
          self.set_series_status_updated)
        self.ui.pushButton_save_series_changes.pressed.connect(\
          self.update_series)
        self.ui.pushButton_revert_series_changes.pressed.connect(\
          self.revert_series)
        self.ui.pushButton_load_local_series_nfo.pressed.connect(\
          self.load_series_nfo)
        self.ui.pushButton_update_series_from_tvdb.pressed.connect(\
          self.update_series_from_tvdb)
        self.ui.line_episode_name.textEdited.connect(\
          self.set_episode_name_updated)
        self.ui.text_episode_plot.textChanged.connect(\
          self.set_episode_plot_updated)
        self.ui.line_airdate.textEdited.connect(\
          self.set_episode_airdate_updated)
        self.ui.line_tvdb_id.textEdited.connect(\
          self.set_episode_id_updated)
        self.ui.line_tvdb_rating.textEdited.connect(\
          self.set_episode_tvdb_rating_updated)
        self.ui.pushButton_save_episode_changes.pressed.connect(\
          self.update_episode)
        self.ui.pushButton_revert_episode_changes.pressed.connect(\
          self.revert_episode)
        self.ui.pushButton_load_local_episode_nfo.pressed.connect(\
          self.load_episode_nfo)
        self.ui.pushButton_update_episode_from_tvdb.pressed.connect(\
          self.update_episode_from_tvdb)
        self.ui.pushButton_new_series_poster.pressed.connect(\
          self.select_series_poster)
        self.ui.pushButton_new_series_wide_banner.pressed.connect(\
          self.select_series_wide_banner)
        self.ui.pushButton_new_season_poster.pressed.connect(\
          self.select_season_poster)
        self.ui.pushButton_new_season_wide.pressed.connect(\
          self.select_season_wide_banner)
        self.ui.pushButton_new_series_fanart.pressed.connect(\
          self.select_series_fanart)
        self.ui.actionScan_Files.triggered.connect(\
          self.scan_files)
        self.ui.actionEdit_Preferences.triggered.connect(\
          self.edit_preferences)
        self.ui.actionClear_Cache.triggered.connect(\
          self.clear_cache)
        self.ui.actionSave_all.triggered.connect(\
          self.save_all)
        self.ui.actionSave_series_artwork.triggered.connect(\
          self.save_series_artwork)
        self.ui.actionSave_series_nfo.triggered.connect(\
          self.save_series_nfo)
        self.ui.actionSave_series_both.triggered.connect(\
          self.save_series_both)
        self.ui.actionSave_episode_artwork.triggered.connect(\
          self.save_episode_artwork)
        self.ui.actionSave_episode_nfo.triggered.connect(\
          self.save_episode_nfo)
        self.ui.actionSave_episode_both.triggered.connect(\
          self.save_episode_both)
        self.save_files.started.connect(self.started_status)
        self.save_files.finished.connect(self.finished_status)
        self.save_files.terminated.connect(self.terminated_status)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("updateStatus(QString)"), \
                     self.update_status)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("updateProgress(int)"), \
                     self.update_progress)
        self.connect(self.save_files, \
                     QtCore.SIGNAL("setupProgress(int)"), \
                     self.setup_progress)

        #Initialize some variables
        self.series_name_updated = 0
        self.series_overview_updated = 0
        self.series_network_updated = 0
        self.series_airtime_updated = 0
        self.series_runtime_updated = 0
        self.series_status_updated = 0
        self.episode_name_updated = 0
        self.episode_plot_updated = 0
        self.episode_airdate_updated = 0
        self.episode_tvdb_rating_updated = 0

        #Create some empty lists for later
        self.series_banners_url = []
        self.series_banners_wide_url = []
        self.series_fanart_banners_url = []
        self.season_banners_url = []
        self.season_banners_wide_url = []

        #Initialize the configuration dialog
        self.config_dialog = ConfigDialog()
        self.config_dialog.accepted.connect(self.read_config)
        
        self.ui.pushButton_save_series_changes.setEnabled(0)
        self.ui.pushButton_revert_series_changes.setEnabled(0)
        self.ui.pushButton_save_episode_changes.setEnabled(0)
        self.ui.pushButton_revert_episode_changes.setEnabled(0)
        self.ui.pushButton_new_series_poster.setEnabled(0)
        self.ui.pushButton_new_series_wide_banner.setEnabled(0)
        self.ui.pushButton_new_season_poster.setEnabled(0)
        self.ui.pushButton_new_season_wide.setEnabled(0)
        self.ui.pushButton_load_local_series_nfo.setEnabled(0)
        self.ui.pushButton_load_local_episode_nfo.setEnabled(0)
        self.ui.pushButton_update_series_from_tvdb.setEnabled(0)
        self.ui.pushButton_update_episode_from_tvdb.setEnabled(0)

        #Put a progress bar on the status bar
        self.pb = QtGui.QProgressBar()
        self.statusBar().addPermanentWidget(self.pb)

    def list_view_clicked(self, index):
        """Determines what was clicked in the column view tree"""
        #other functions need to know where we are in the tree
        self.index = index
        #Find the series we are working with
        self.series_name = index.data().toString()
        self.clear_season_info()
        self.clear_episode_info()
        self.set_column_view()
        self.set_series_info(0)
        self.ui.pushButton_save_series_changes.setEnabled(0)
        self.ui.pushButton_revert_series_changes.setEnabled(0)
        self.ui.pushButton_new_series_poster.setEnabled(1)
        self.ui.pushButton_new_series_wide_banner.setEnabled(1)
        self.ui.pushButton_new_season_poster.setEnabled(0)
        self.ui.pushButton_new_season_wide.setEnabled(0)

    def column_view_clicked(self, index):
        """Determines what was clicked in the column view tree"""
        #other functions need to know where we are in the tree
        self.index = index
        #Find the series we are working with
        this_node_data = index.data().toString()
        parent = index.parent()
        parent_data = parent.data().toString()

        if parent_data == "":    #we are at the season level
            season_number = this_node_data
            if str(season_number) == 'Specials':
                self.season_number = 0 
            else:
                self.season_number = int(season_number)
            self.clear_episode_info()
            self.set_season_info()
            self.ui.pushButton_new_season_poster.setEnabled(1)
            self.ui.pushButton_new_season_wide.setEnabled(1)
        else:                           #we are at the episode level
            season_number = parent_data
            if str(season_number) == 'Specials':
                self.season_number = 0 
            else:
                self.season_number = int(season_number)
            self.episode_number = \
              int(str(this_node_data.split("-")[0]).rstrip())
            self.set_season_info()
            self.set_episode_info()
            self.ui.pushButton_save_episode_changes.setEnabled(0)
            self.ui.pushButton_revert_episode_changes.setEnabled(0)

    def set_series_name_updated(self, text):
        self.series_name_updated = 1
        self.new_series_name = str(text)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_series_overview_updated(self):
        self.series_overview_updated = 1
        self.new_series_overview = \
          unicode(self.ui.plainTextEdit_overview.toPlainText(), "latin-1")
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_series_network_updated(self, text):
        self.series_network_updated = 1
        self.new_series_network = str(text)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_series_airtime_updated(self, text):
        self.series_airtime_updated = 1
        self.new_series_airtime = str(text)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_series_runtime_updated(self, text):
        self.series_runtime_updated = 1
        self.new_series_runtime = str(text)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_series_status_updated(self, text):
        self.series_status_updated = 1
        self.new_series_status = str(text)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def update_series(self):
        series_id = dbTV.get_series_id(self.series_name)
        if self.series_name_updated == 1:
            dbTV.update_series_field('name', self.new_series_name, series_id)
            self.series_name=self.new_series_name
        if self.series_overview_updated == 1:
            dbTV.update_series_field('overview', \
                                     self.new_series_overview, series_id)
        if self.series_network_updated == 1:
            pass
        if self.series_airtime_updated == 1:
            new_series_airs_time = self.new_series_airtime.split(' at ')[1]
            new_series_airs_day = self.new_series_airtime.split(' at ')[0]
            dbTV.update_series_field('airs_time', \
                                     new_series_airs_time, series_id)
            dbTV.update_series_field('airs_day', \
                                     new_series_airs_day, series_id)
        if self.series_runtime_updated == 1:
            dbTV.update_series_field('runtime', \
                                     self.new_series_runtime, series_id)
        if self.series_status_updated == 1:
            dbTV.update_series_field('status', \
                                     self.new_series_status, series_id)
        self.ui.pushButton_save_series_changes.setEnabled(0)
        self.ui.pushButton_revert_series_changes.setEnabled(0)

    def revert_series(self):
        self.set_series_info(0)
        self.ui.pushButton_save_series_changes.setEnabled(0)
        self.ui.pushButton_revert_series_changes.setEnabled(0)

    def load_series_nfo(self):
        series_id = dbTV.get_series_id(self.series_name)
        series_nfo = dbTV.get_series_nfo_filename(series_id)
        series_doc = nfo_reader.readNfo(series_nfo)
        self.set_series_info_from_dom(series_doc, 0)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def update_series_from_tvdb(self):
        series_id = dbTV.get_series_id(self.series_name)
        series = TVDB.get_series_info(series_id)
        dom = dom_from_series(series)
        self.set_series_info_from_dom(dom, 0)
        self.ui.pushButton_save_series_changes.setEnabled(1)
        self.ui.pushButton_revert_series_changes.setEnabled(1)

    def set_episode_name_updated(self, text):
        self.episode_name_updated = 1
        self.new_episode_name = str(text)
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def set_episode_plot_updated(self):
        self.episode_plot_updated = 1
        self.new_episode_plot = \
          str(self.ui.text_episode_plot.toPlainText().toUtf8())
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def set_episode_airdate_updated(self, text):
        self.episode_airdate_updated = 1
        self.new_episode_airdate = str(text)
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def set_episode_id_updated(self, text):
        ### FIXME ###
        self.episode_id_updated = 1
        self.new_episode_id = str(text)
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def set_episode_tvdb_rating_updated(self, text):
        self.episode_tvdb_rating_updated = 1
        self.new_episode_tvdb_rating = str(text)
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def update_episode(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        if self.episode_name_updated == 1:
            dbTV.update_episode_field('name', \
                                      self.new_episode_name, episode_id)
        if self.episode_plot_updated == 1:
            dbTV.update_episode_field('overview', \
                                      self.new_episode_plot, episode_id)
        if self.episode_airdate_updated == 1:
            dbTV.update_episode_field('first_aired', \
                                      self.new_episode_airdate, episode_id)
        if self.episode_tvdb_rating_updated == 1:
            dbTV.update_episode_field('rating', \
                                      self.new_episode_tvdb_rating, episode_id)
        self.ui.pushButton_save_episode_changes.setEnabled(0)
        self.ui.pushButton_revert_episode_changes.setEnabled(0)

    def revert_episode(self):
        self.set_episode_info()
        self.ui.pushButton_save_episode_changes.setEnabled(0)
        self.ui.pushButton_revert_episode_changes.setEnabled(0)

    def load_episode_nfo(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        episode_nfo = dbTV.get_episode_nfo_filename(episode_id)
        dom = nfo_reader.readNfo(episode_nfo)
        if dom is not None:
            self.set_episode_info_from_dom(dom)
            self.ui.pushButton_save_episode_changes.setEnabled(1)
            self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def update_episode_from_tvdb(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        episode = TVDB.get_episode_info(episode_id)
        dom = dom_from_episode(episode)
        self.set_episode_info_from_dom(dom)
        self.ui.pushButton_save_episode_changes.setEnabled(1)
        self.ui.pushButton_revert_episode_changes.setEnabled(1)

    def set_column_view(self):
        dom = dbTV.make_seasons_episodes_dom(self.series_name)
        model = SeasonEpisodeModel(dom)
        self.ui.columnView_season_episode.setModel(model)
        self.ui.columnView_season_episode.setColumnWidths([300,550,50])

    def set_season_info(self):
        """Sets the info for the current season in the display window"""
        series_id = dbTV.get_series_id(self.series_name)
        season_list = dbTV.make_episodes_list(series_id, self.season_number)
        model = SeasonListModel(season_list)
        self.ui.listView_season_episode_full.setModel(model)
        self.selected_season_poster = dbTV.get_selected_banner_url(\
          series_id, 'season', self.season_number)
        if not self.selected_season_poster == "":
            filename = TVDB.retrieve_banner(self.selected_season_poster)
            season_poster_pixmap = QtGui.QPixmap(filename).scaled(300, 450,\
                                                  QtCore.Qt.KeepAspectRatio)
            self.ui.label_season_poster.setPixmap(season_poster_pixmap)
        else:
            self.ui.label_season_poster.clear()
            self.ui.label_season_poster.setText("No season poster selected")
        self.selected_season_banner_wide = dbTV.get_selected_banner_url(\
          series_id, 'seasonwide', self.season_number)
        if not self.selected_season_banner_wide == "":
            filename = TVDB.retrieve_banner(self.selected_season_banner_wide)
            season_banner_wide_pixmap = \
              QtGui.QPixmap(filename).scaledToHeight(140)
            self.ui.label_season_banner_wide.setPixmap(\
              season_banner_wide_pixmap)
        else:   
            self.ui.label_season_banner_wide.clear()
            self.ui.label_season_banner_wide.setText(\
              "No season wide banner selected")

    def set_series_info(self, tab_index):
        #Get the series id from the database
        series_id = dbTV.get_series_id(self.series_name)

        #Create a QDomDocument containing the series details
        series_doc = dbTV.make_series_dom(series_id)
        self.set_series_info_from_dom(series_doc, tab_index)        
        self.ui.pushButton_load_local_series_nfo.setEnabled(1)
        self.ui.pushButton_update_series_from_tvdb.setEnabled(1)

    def set_series_info_from_dom(self, series_doc, tab_index):
        """Sets the info for the current series in the display window"""
        series_root = series_doc.firstChildElement('tvshow')
        #Extract the details and fill in the display
        elem_series_name = series_root.firstChildElement('title')
        series_name = elem_series_name.text()
        self.ui.lineEdit_series_name.setText(series_name)

        elem_series_plot = series_root.firstChildElement('plot')
        series_plot = QtCore.QString(elem_series_plot.text())
        self.ui.plainTextEdit_overview.setPlainText(series_plot)

        series_actors = []
        self.ui.combo_actors.clear()
        elem_series_actor = series_root.firstChildElement('actor')
        while not elem_series_actor.isNull():
            elem_series_actor_name = \
              elem_series_actor.firstChildElement('name')
            series_actor_name = elem_series_actor_name.text()
            if not series_actor_name in series_actors:
                series_actors.append(series_actor_name)
            elem_series_actor = elem_series_actor.nextSiblingElement('actor')

        series_actors.sort()
        for series_actor in series_actors:
            self.ui.combo_actors.addItem(series_actor)

        elem_series_network = series_root.firstChildElement('network')
        series_network = elem_series_network.text()
        self.ui.lineEdit_network.setText(series_network)

        elem_series_airs_day = series_root.firstChildElement('airsday')
        series_airs_day = elem_series_airs_day.text()
        elem_series_airs_time = series_root.firstChildElement('airstime')
        series_airs_time = elem_series_airs_time.text()
        if not series_airs_day == '':
            series_airtime = series_airs_day + " at " + series_airs_time
        else:
            series_airtime = ''
        self.ui.lineEdit_airtime.setText(series_airtime)

        elem_series_runtime = series_root.firstChildElement('runtime')
        series_runtime = elem_series_runtime.text()
        self.ui.lineEdit_runtime.setText(series_runtime)

        elem_series_status = series_root.firstChildElement('status')
        series_status = elem_series_status.text()
        self.ui.lineEdit_status.setText(series_status)

        series_id = dbTV.get_series_id(self.series_name)
        self.ui.lineEdit_tvdb_series_id.setText(str(series_id))        

        self.selected_series_poster = \
          dbTV.get_selected_banner_url(series_id, 'poster', '')
        if not self.selected_series_poster == "":
            filename = TVDB.retrieve_banner(self.selected_series_poster)
            series_poster_pixmap = QtGui.QPixmap(filename).scaledToHeight(450)
            self.ui.label_series_banner.setPixmap(series_poster_pixmap)
        else:
            self.ui.label_series_banner.clear()
            self.ui.label_series_banner.setText("No series poster selected")

        self.selected_series_wide_banner = \
          dbTV.get_selected_banner_url(series_id, 'series', '')
        if not self.selected_series_wide_banner == "":
            filename = TVDB.retrieve_banner(self.selected_series_wide_banner)
            series_wide_pixmap = QtGui.QPixmap(filename).scaledToHeight(140)
            self.ui.label_banner_wide.setPixmap(series_wide_pixmap)
        else:
            self.ui.label_banner_wide.clear()
            self.ui.label_banner_wide.setText("No series wide banner selected")

        self.selected_series_fanart = \
          dbTV.get_selected_banner_url(series_id, 'fanart', '')
        if not self.selected_series_fanart == "":
            filename = TVDB.retrieve_banner(self.selected_series_fanart)
            series_fanart_pixmap = QtGui.QPixmap(filename).scaledToHeight(480)
            self.ui.label_series_fanart.setPixmap(series_fanart_pixmap)
        else:
            self.ui.label_series_fanart.clear()
            self.ui.label_series_fanart.setText("No fanart selected")

        self.ui.tabWidget_tv_info.setCurrentIndex(tab_index)

    def set_episode_info(self):
        """Sets the info for the show in the display window"""
        #Get the episode_id from the database
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)

        #Create a QDomDocument containing the episode details
        dom = dbTV.make_episode_dom(episode_id)
        self.set_episode_info_from_dom(dom)
        self.ui.pushButton_load_local_episode_nfo.setEnabled(1)
        self.ui.pushButton_update_episode_from_tvdb.setEnabled(1)

    def set_episode_info_from_dom(self, dom):
        """Sets the info for the show in the display window"""
        episode_root = dom.firstChildElement('episodedetails')

        #Extract the details and fill in the display
        elem_episode_title = episode_root.firstChildElement('title')
        episode_title = elem_episode_title.text()
        self.ui.line_episode_name.setText(episode_title)

        elem_episode_plot = episode_root.firstChildElement('plot')
        episode_plot = QtCore.QString(elem_episode_plot.text())
        self.ui.text_episode_plot.setPlainText(episode_plot)

        elem_episode_thumb = episode_root.firstChildElement('thumb')
        if not elem_episode_thumb.isNull():
            episode_thumb = elem_episode_thumb.text()
        else:
            episode_thumb = "none"
        #Set the preview image
        image_file = TVDB.retrieve_banner(str(episode_thumb))
        if image_file is not None:
            image = QtGui.QPixmap(image_file)
            self.ui.label_episode_thumb.setPixmap(image)

        elem_episode_airdate = episode_root.firstChildElement('aired')
        episode_airdate = elem_episode_airdate.text()
        self.ui.line_airdate.setText(episode_airdate)

        elem_episode_id = episode_root.firstChildElement('id')
        episode_id = elem_episode_id.text()
        self.ui.line_tvdb_id.setText(episode_id)

        elem_episode_rating = episode_root.firstChildElement('rating')
        episode_rating = elem_episode_rating.text()
        self.ui.line_tvdb_rating.setText(episode_rating)

        elem_episode_directors = episode_root.firstChildElement('director')
        episode_directors = unicode(elem_episode_directors.text(), \
          "latin-1").split('|')
        self.ui.combo_directors.clear()
        for director in episode_directors:
            self.ui.combo_directors.addItem(director)

        elem_episode_writers = episode_root.firstChildElement('credits')
        episode_writers = unicode(elem_episode_writers.text(), \
          "latin-1").split('|')
        self.ui.combo_writers.clear()
        for writer in episode_writers:
            self.ui.combo_writers.addItem(writer)

        episode_actors = []
        elem_episode_actor = episode_root.firstChildElement('actor')
        self.ui.combo_guests.clear()
        while not elem_episode_actor.isNull():
            elem_episode_actor_name = \
              elem_episode_actor.firstChildElement('name')
            episode_actor_name = elem_episode_actor_name.text()
            episode_actors.append(episode_actor_name)
            elem_episode_actor = elem_episode_actor.nextSiblingElement('actor')

        episode_actors = set(episode_actors)
        for episode_actor in episode_actors:
            if self.ui.combo_actors.findText(episode_actor) < 0:
                self.ui.combo_guests.addItem(episode_actor)

        self.ui.tabWidget_tv_info.setCurrentIndex(3)

    def clear_episode_info(self):
        """Clears the episode info from the display window"""
        self.ui.line_episode_name.clear()
        self.ui.text_episode_plot.clear()
        self.ui.line_airdate.clear()
        self.ui.line_tvdb_id.clear()
        self.ui.line_tvdb_rating.clear()
        self.ui.combo_directors.clear()
        self.ui.combo_writers.clear()
        self.ui.combo_guests.clear()
        self.ui.label_episode_thumb.clear()
        
    def clear_season_info(self):
        model = EmptyListModel()
        self.ui.listView_season_episode_full.setModel(model)
        self.ui.label_season_poster.clear()
        self.ui.label_season_banner_wide.clear()

    def select_series_poster(self):
        self.logger.info("Selecting new series poster")
        banner_dialog = BannerDialog(self.series_name, "series_posters", 0)
        accepted = banner_dialog.exec_()
        if accepted:
            self.set_series_info(0)
        self.ui.pushButton_new_series_poster.setDown(False)

    def select_series_wide_banner(self):
        banner_dialog = BannerDialog(self.series_name, "series_wide", 0)
        accepted = banner_dialog.exec_()
        if accepted:
            self.set_series_info(0)
        self.ui.pushButton_new_series_wide_banner.setDown(False)

    def select_series_fanart(self):
        banner_dialog = BannerDialog(self.series_name, "series_fanart", 0)
        accepted = banner_dialog.exec_()
        if accepted:
            self.set_series_info(1)
        self.ui.pushButton_new_series_fanart.setDown(False)

    def select_season_poster(self):
        banner_dialog = BannerDialog(self.series_name, \
                                     "season_posters", \
                                      self.season_number)
        accepted = banner_dialog.exec_()
        if accepted:
            self.set_season_info()
        self.ui.pushButton_new_season_poster.setDown(False)

    def select_season_wide_banner(self):
        banner_dialog = BannerDialog(self.series_name, \
                                     "season_wide", \
                                     self.season_number)
        accepted = banner_dialog.exec_()
        if accepted:
            self.set_season_info()
        self.ui.pushButton_new_season_wide.setDown(False)

    def scan_files(self):
        for video_dir in config.tv_dirs:
            self.progress.setLabelText("Scanning Files from %s into DB..." \
                                       %  (video_dir))
            self.logger.info("Scanning files")
            scanner = Scanner(video_dir)
            scanner.set_series_list()
            self.progress.setMaximum(len(scanner.series_list))
            self.progress.setValue(0)
            self.logger.debug(scanner.series_list)
            for series_name in scanner.series_list:
                self.progress.setValue(scanner.series_list.index(series_name))
                self.progress.show()
                match_list = scanner.get_series_id_list(series_name)
                if len(match_list) == 0:
                    self.logger.info("No matches found on thetvdb.com for '%s'." % (series_name))
                ### FIXME ###
                    series_id = raw_input("Please input the ID for the correct series:")
                elif len(match_list) == 1:
                    self.logger.info("Found match for '%s'." % (series_name))
                    series_id = match_list[0][0]
                else:
                    match = False
                    list = ''
                    for i in range(0,len(match_list)):
                        if match_list[i][1] == series_name:
                            self.logger.info("Found match for '%s'." % (series_name))
                            series_id = match_list[i][0]
                            match = True
                        else:
                            list += "[%d] %s (%s)\n " % (i, match_list[i][1], \
                                                         match_list[i][0])
                    if not match:
                        selection = self.input_dialog.getInt(self, '', \
                                    "Select best match:\n %s" % (list), \
                                    0, 0, len(match_list) - 1)[0]
                        try:
                            series_id = match_list[selection][0]
                        except IndexError:
                            self.logger.info("That is not an option.")
                if config.prefer_local:
                    self.logger.info("Adding info from local nfo files")
                    scanner.add_series_to_db_by_nfo(series_name)
                else:
                    self.logger.info("Adding info from thetvdb.com")
                    scanner.add_series_to_db_by_id(series_id)
                self.logger.info("Adding files to db.")
                scanner.add_files_to_db(series_id, series_name)
            dbTV.remove_shows_with_no_files()
            scanner.__del__()
            self.progress.setValue(len(scanner.series_list))

        self.logger.info("Finished Scanning")
        #Create a dom representing the shows in the database
        shows = dbTV.make_shows_list()
        #Turn that into a model
        model = ShowListModel(shows)
        #Set that as the model for the listView
        self.ui.listView_shows.setModel(model)

    def edit_preferences(self):
        self.config_dialog.show()

    def read_config(self):
        config.read_config_file()

    def clear_cache(self):
        top = os.path.join(config.config_dir, "cache")
        for root, dirs, files in os.walk(top, topdown=False):
            for name in files:
                os.remove(os.path.join(root, name))
            for name in dirs:
                os.rmdir(os.path.join(root, name))

    def save_all(self):
        self.save_files.save_all(self.shows)

    def save_series_artwork(self):
        series_id = dbTV.get_series_id(self.series_name)
        self.save_files.save_series_artwork(series_id)

    def save_series_nfo(self):
        series_id = dbTV.get_series_id(self.series_name)
        self.save_files.save_series_nfos(series_id)

    def save_series_both(self):
        series_id = dbTV.get_series_id(self.series_name)
        self.save_files.save_series_both(series_id)

    def save_episode_artwork(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        dbTV.write_episode_thumb(episode_id)

    def save_episode_nfo(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        dbTV.write_episode_nfo(episode_id)

    def save_episode_both(self):
        episode_id = dbTV.get_episode_id(self.series_name, \
                                         self.season_number, \
                                         self.episode_number)
        dbTV.write_episode_nfo(episode_id)
        dbTV.write_episode_thumb(episode_id)

    def started_status(self):
        self.statusBar().showMessage("Saving files.")
        self.pb.show()

    def finished_status(self):
        self.pb.hide()
        self.statusBar().showMessage("File saving finished.")

    def terminated_status(self):
        self.pb.hide()
        self.statusBar().showMessage("File saving terminated.")

    def update_status(self, show):
        self.statusBar().showMessage("Saving info and artwork for %s" % (show,))

    def update_progress(self, progress):
        self.pb.setValue(progress)

    def setup_progress(self, max):
        self.pb.setRange(0, max)
示例#21
0
class MainWindow(QMainWindow):
    settings_button_clicked = pyqtSignal()
    status_table_clicked = pyqtSignal(str)
    export_accounting = pyqtSignal(str, str, str)


    def __init__(self):
        # Init the base class
        QMainWindow.__init__(self)

        self._settings = load_settings(Config.DEFAULT_SETTINGS)

        # Init the processed .ui file
        self._ui = Ui_MainWindow()
        self._ui.setupUi(self)
        self.setWindowTitle("TradeSkillMaster Application r{}".format(Config.CURRENT_VERSION))

        # connect signals / slots
        self._ui.addon_status_table.doubleClicked.connect(self._addon_status_table_clicked)
        self._ui.backup_status_table.doubleClicked.connect(self._backup_status_table_clicked)
        self._ui.settings_button.clicked.connect(self.settings_button_clicked.emit)
        self._ui.accounts_dropdown.activated['QString'].connect(self.accounts_dropdown_changed)
        self._ui.realm_dropdown.activated['QString'].connect(self.realm_dropdown_changed)
        self._ui.export_button.clicked.connect(self.export_button_clicked)
        self._ui.help_button.setProperty("url", "http://tradeskillmaster.com/site/getting-help")
        self._ui.help_button.clicked.connect(self._link_button_clicked)
        self._ui.premium_button.setProperty("url", "http://tradeskillmaster.com/premium")
        self._ui.premium_button.clicked.connect(self._link_button_clicked)
        self._ui.logo_button.setProperty("url", "http://tradeskillmaster.com")
        self._ui.logo_button.clicked.connect(self._link_button_clicked)
        self._ui.twitter_button.setProperty("url", "http://twitter.com/TSMAddon")
        self._ui.twitter_button.clicked.connect(self._link_button_clicked)

        # Apply the stylesheet
        file = QFile(":/resources/main_window.css")
        file.open(QIODevice.ReadOnly)
        data = str(file.readAll(), encoding="ascii")
        self.setStyleSheet(data)

        # set properties which are necessary for tweaking the style
        self._ui.help_button.setProperty("id", "premiumButton")
        self._ui.premium_button.setProperty("id", "premiumButton")
        self._ui.header_text.setProperty("id", "headerText")

        # stylesheet tweaks for things which don't work when put into the .css for some unknown reason
        self._ui.accounting_tab.setStyleSheet("QCheckBox:disabled { color : #666; } QCheckBox { color : white; }");

        self._sync_status_table_model = TableModel(self, ['Region/Realm', 'AuctionDB', 'Great Deals', 'Last Updated'])
        self._ui.sync_status_table.setModel(self._sync_status_table_model)

        self._addon_status_table_model = TableModel(self, ['Name', 'Version', 'Status'])
        self._ui.addon_status_table.setModel(self._addon_status_table_model)

        self._backup_status_table_model = TableModel(self, ['System ID', 'Account', 'Timestamp', 'Sync Status'])
        self._ui.backup_status_table.setModel(self._backup_status_table_model)

        self._accounting_info = {}
        self._accounting_current_account = ""
        self._accounting_current_realm = ""

        if Config.IS_WINDOWS:
            # create the system tray icon / menu
            self._tray_icon = QSystemTrayIcon(QIcon(":/resources/logo.png"), self)
            self._tray_icon.setToolTip("TradeSkillMaster Application r{}".format(Config.CURRENT_VERSION))
            self._tray_icon.activated.connect(self._icon_activated)
            tray_icon_menu = QMenu(self)
            restore_action = QAction("Restore", tray_icon_menu)
            restore_action.triggered.connect(self._restore_from_tray)
            tray_icon_menu.addAction(restore_action)
            tray_icon_menu.addSeparator()
            quit_action = QAction("Quit", tray_icon_menu)
            quit_action.triggered.connect(self.close)
            tray_icon_menu.addAction(quit_action)
            self._tray_icon.setContextMenu(tray_icon_menu)
            self._tray_icon.hide()


    def __del__(self):
        if Config.IS_WINDOWS:
            self._tray_icon.hide()


    def changeEvent(self, event):
        if not Config.IS_WINDOWS:
            return
        if event.type() == QEvent.WindowStateChange:
            if self.isMinimized() and self._settings.minimize_to_tray:
                logging.getLogger().info("Minimizing to the system tray")
                self._tray_icon.show()
                self.hide()
                event.ignore()


    def closeEvent(self, event):
        if self._settings.confirm_exit:
            msg_box = QMessageBox()
            msg_box.setWindowIcon(QIcon(":/resources/logo.png"))
            msg_box.setWindowModality(Qt.ApplicationModal)
            msg_box.setIcon(QMessageBox.Information)
            msg_box.setText("Are you sure you want to exit?")
            msg_box.setStandardButtons(QMessageBox.Cancel | QMessageBox.Yes)
            if msg_box.exec_() != QMessageBox.Yes:
                event.ignore()
                return
        event.accept()


    def set_visible(self, visible):
        self.setVisible(visible)
        if self._settings.start_minimized and Config.IS_WINDOWS:
            self.showMinimized()
            self.setWindowState(Qt.WindowMinimized)
            if self._settings.minimize_to_tray:
                logging.getLogger().info("Minimizing to the system tray")
                self._tray_icon.show()
                self.hide()
            else:
                logging.getLogger().info("Minimizing")


    def _restore_from_tray(self):
        if not Config.IS_WINDOWS:
            return
        logging.getLogger().info("Restoring from the system tray")
        self.show()
        self.setWindowState(Qt.WindowActive)
        self._tray_icon.hide()


    def _icon_activated(self, reason):
        if not Config.IS_WINDOWS:
            return
        if reason == QSystemTrayIcon.Trigger or reason == QSystemTrayIcon.DoubleClick:
            self._restore_from_tray()


    def _link_button_clicked(self):
        QDesktopServices.openUrl(QUrl(self.sender().property("url")))


    def _addon_status_table_clicked(self, index):
        key = self._addon_status_table_model.get_click_key(index)
        if key:
            self.status_table_clicked.emit(key)


    def _backup_status_table_clicked(self, index):
        key = self._backup_status_table_model.get_click_key(index)
        if key:
            self.status_table_clicked.emit(key)


    def set_sync_status_data(self, data):
        self._sync_status_table_model.set_info(data)
        self._ui.sync_status_table.resizeColumnsToContents()
        self._ui.sync_status_table.sortByColumn(0, Qt.AscendingOrder)


    def set_addon_status_data(self, data):
        self._addon_status_table_model.set_info(data)
        self._ui.addon_status_table.resizeColumnsToContents()
        self._ui.addon_status_table.sortByColumn(0, Qt.AscendingOrder)


    def set_backup_status_data(self, data):
        system_text = "The system ID is unique to the computer you are running the desktop app from. " \
                      "<a href=\"http://tradeskillmaster.com/user/backups\" style=\"color: #EC7800\">Premium users " \
                      "can sync backups</a> to the cloud and across multiple computers. Otherwise, only backups from " \
                      "the local system (<font style=\"color: cyan\">{}</font>) will be listed below.<br><br>To " \
                      "restore a backup, double-click on the row in the table below.".format(Config.SYSTEM_ID)
        self._ui.backup_system_text.setText(system_text)
        self._backup_status_table_model.set_info(data)
        self._ui.backup_status_table.resizeColumnsToContents()
        self._ui.backup_status_table.sortByColumn(2, Qt.DescendingOrder)


    def show_notification(self, message, critical):
        if not Config.IS_WINDOWS:
            return
        icon = QSystemTrayIcon.Critical if critical else QSystemTrayIcon.NoIcon
        if self._tray_icon.isVisible():
            self._tray_icon.showMessage("TradeSkillMaster Desktop Application", message, icon)
        else:
            # The tray icon needs to be visible to show the message, but we can immediately hide it afterwards
            # This is the behavior on Windows 10 at least...need to confirm on other operating systems
            self._tray_icon.show()
            self._tray_icon.showMessage("TradeSkillMaster Desktop Application", message, icon)
            self._tray_icon.hide()


    def _update_dropdown(self, dropdown, items, selected_item):
        items = [""] + items
        selected_index = 0
        dropdown.clear()
        for index, item in enumerate(items):
            if item == selected_item:
                selected_index = index
            dropdown.addItem(item)
        dropdown.setCurrentIndex(selected_index)


    def _update_accounting_tab(self):
        # update the accounts dropdown
        accounts = [x for x in self._accounting_info if self._accounting_info[x]]
        self._update_dropdown(self._ui.accounts_dropdown, accounts, self._accounting_current_account)

        # update the realm dropdown
        self._ui.realm_dropdown.setEnabled(self._accounting_current_account != "")
        if self._accounting_current_account != "":
            self._update_dropdown(self._ui.realm_dropdown,
                                  self._accounting_info[self._accounting_current_account],
                                  self._accounting_current_realm)

        # update the export button
        self._ui.export_button.setEnabled(self._accounting_current_realm != "")


    def set_accounting_accounts(self, info):
        self._accounting_info = info
        self._update_accounting_tab()


    def accounts_dropdown_changed(self, account):
        self._accounting_current_account = account
        self._accounting_current_realm = ""
        self._update_accounting_tab()


    def realm_dropdown_changed(self, realm):
        assert(self._accounting_current_account)
        self._accounting_current_realm = realm
        self._update_accounting_tab()


    def export_button_clicked(self):
        self._ui.export_button.setEnabled(False)
        self._ui.export_button.setText("Exporting...")
        def do_export():
            if self._ui.sales_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "sales")
            if self._ui.purchases_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "purchases")
            if self._ui.income_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "income")
            if self._ui.expenses_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "expenses")
            if self._ui.expired_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "expired")
            if self._ui.canceled_checkbox.checkState():
                self.export_accounting.emit(self._accounting_current_account, self._accounting_current_realm, "canceled")
            self._ui.export_button.setEnabled(True)
            self._ui.export_button.setText("Export to CSV")

            # show a popup saying we've exported everything
            msg_box = QMessageBox()
            msg_box.setWindowIcon(QIcon(":/resources/logo.png"))
            msg_box.setWindowModality(Qt.ApplicationModal)
            msg_box.setIcon(QMessageBox.Information)
            msg_box.setText("The TSM_Accounting data has been successfully exported to your desktop.")
            msg_box.setStandardButtons(QMessageBox.Ok)
            msg_box.exec_()
        # slight delay so the button gets disabled
        QTimer.singleShot(1, do_export)
示例#22
0
class DelphosWindow(QMainWindow):
    """Manages the main Delphos window interface (Ui_MainWindow)
    """
    def __init__(self, gui_manager):
        QMainWindow.__init__(self, None)    #Initialize myself as a widget
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)    #Create the components of the window
        
        self.gui_manager = gui_manager
        
        self.dock_full_screen = False
        self.min_doc_dock_width = 200
        
        #Maximize the display to full size
        #self.showMaximized()

        #Add status bar at bottom of window
        self.statusbar = QtGui.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)
        
        #Add progress bar to status bar
        self.pb = QProgressBar(self.statusBar())
        self.pb.setMinimum(0)
        self.pb.setMaximum(0)
        self.statusbar.addPermanentWidget(self.pb)        
        self.pb.hide()
        
        QObject.connect(self.ui.menu_dock_visible, SIGNAL("triggered()"), self.toggle_documentation_window)
        QObject.connect(self.ui.dock_doc, SIGNAL("visibilityChanged(bool)"), self.toggle_dock_visible_menu)

        QObject.connect(self.ui.menu_dock_floating, SIGNAL("triggered()"), self.toggle_dock_float)
        QObject.connect(self.ui.dock_doc, SIGNAL("topLevelChanged(bool)"), self.toggle_dock_floating_menu)

        QObject.connect(self.ui.menu_open_full_doc, SIGNAL("triggered()"), self.load_full_doc)

        #self.ui.dock_doc.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    def load_full_doc(self, project_type=None, language=None):
        """Load full documentation in external application
        """
        #Find which documentation subdir to look in
        if not project_type:
            project_type = self.gui_manager.project_manager.get_current_project_type()
        if not language:
            language = self.gui_manager.config_manager.get_language()
            
        if project_type == 'fisheries':
            if language == 'english':
                doc_subdir = 'fisheries'+os.sep+'english'+os.sep
            else:
                doc_subdir = 'fisheries'+os.sep+'spanish'+os.sep
        elif project_type == 'sites':
            if language == 'english':
                doc_subdir = 'sites'+os.sep+'english'+os.sep
            else:
                doc_subdir = 'sites'+os.sep+'spanish'+os.sep
        elif project_type == 'communities':
            if language == 'english':
                doc_subdir = 'communities'+os.sep+'english'+os.sep
            else:
                doc_subdir = 'communities'+os.sep+'spanish'+os.sep                
        
        doc_path = os.getcwd()+os.sep+"documentation"+os.sep+doc_subdir+'documentation.html'
        doc_url = "file:"+urllib.pathname2url(unicode(doc_path))

        #file:///U|/dev/delphos/src/documentation/fisheries/english/letter_to_experts.doc
        self.gui_manager.desktop_services.openUrl(QUrl(doc_url))
                                      
    def load_toc(self, project_type=None, language=None):
        """Loads the table of contents within the dock widget
        """
        #Find which toc data to load
        if not project_type:
            project_type = self.gui_manager.project_manager.get_current_project_type()
        if not language:
            language = self.gui_manager.config_manager.get_language()
        
        toc = ""
        if project_type == 'fisheries':
            if language == 'english':
                toc = fisheries_english_toc
            else:
                toc = fisheries_spanish_toc
        elif project_type == 'communities':
            if language == 'english':
                toc = communities_english_toc
            else:
                toc = communities_spanish_toc
        elif project_type == 'sites':        
            if language == 'english':
                toc = sites_english_toc
            else:
                toc = sites_spanish_toc        	        
        self.process_toc(deepcopy(toc))
    
    def process_toc(self, toc):
        self.ui.toc_tree.clear()
        #Make a copy as original will be destroyed
        for heading in toc:
            root_item = self.ui.toc_tree.invisibleRootItem()
            self.process_heading(heading, root_item)
    
    def process_heading(self, heading, parent):
        #print type(heading)
        if type(heading) == str:
            tree_item = QTreeWidgetItem(parent)
            tree_item.setText(0, heading)
        if type(heading) == dict:
            (heading_name, subheadings) = heading.popitem()
            tree_item = QTreeWidgetItem(parent)
            tree_item.setText(0, heading_name)
            for subheading in subheadings:
                self.process_heading(subheading, tree_item)                               

    def process_toc_click(self, item, column):
        """Builds URL from toc heading name and reloads doc editor
        """
        heading = item.text(column)
        #Morph heading name into anchor label name
        label = heading.replace(' ', '_')
        label = heading.replace('/', '_')
        label = heading.replace('.', '')
        label = label.toLower()
        
        #Build URL
        project_type = self.gui_manager.project_manager.get_current_project_type()
        language = self.gui_manager.config_manager.get_language()
        #Load URL and go to anchor within it
        self.ui.doc_browser.load_anchor(label, project_type, language)

    def process_help_click(self, en_name, sp_name):
        """Uses the help type given to load a section of the documentation
        """
        en_label = en_name.replace('help_', '')
        sp_label = sp_name.replace('help_', '')
            
        #Build URL
        project_type = self.gui_manager.project_manager.get_current_project_type()
        language = self.gui_manager.config_manager.get_language()
        #Load URL and go to anchor within it
        if language == 'english':
            self.ui.doc_browser.load_anchor(en_label, project_type, language)
        elif language == 'spanish':
            self.ui.doc_browser.load_anchor(sp_label, project_type, language)
            
        #Show the documentation if its hidden        
        if not self.ui.dock_doc.isVisible():
            self.ui.menu_dock_visible.trigger()
            

    def dock_full_screen(self):
        return self.dock_full_screen

    def toggle_dock(self):
         if self.dock_full_screen:
             
             self.ui.dock_doc.setMinimumSize(self.min_doc_dock_width, 0)
             self.ui.dock_doc.resize(self.min_doc_dock_width, self.ui.dock_doc.height())

             doc_dock_size = self.ui.dock_doc.sizeHint()

             self.ui.toc_box.resize(100, self.ui.toc_box.height())
             self.ui.toc_tree.resize(100, self.ui.toc_box.height())
             self.ui.doc_box.resize(100, self.ui.doc_box.height())
             self.ui.doc_browser.resize(100, self.ui.toc_box.height())
             self.dock_full_screen = False
         else:
             self.ui.dock_doc.setMinimumSize(self.width(), 0)
             self.dock_full_screen = True

    def toggle_documentation_window(self):
        if self.ui.dock_doc.isVisible():
            self.ui.dock_doc.hide()
        else:            
            self.ui.dock_doc.show()

    def toggle_dock_visible_menu(self):
        if self.ui.dock_doc.isVisible():
            self.ui.menu_dock_visible.setChecked(True)
        else:            
            self.ui.menu_dock_visible.setChecked(False)

    def toggle_dock_float(self):
        if self.ui.dock_doc.isFloating():
            self.ui.dock_doc.setFloating(False)
        else:            
            self.ui.dock_doc.setFloating(True)

    def toggle_dock_floating_menu(self, isFloating):
        if isFloating:
            self.ui.menu_dock_floating.setChecked(False)
        else:            
            self.ui.menu_dock_floating.setChecked(True)
示例#23
0
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.mdiArea.setOption(QMdiArea.DontMaximizeSubWindowOnActivation, True)

    @pyqtSlot(int)
    def show_child_window(self, widget_number):
        if widget_number == 0:
            self.deliver_widget = DeliverWindow()
            self.deliver_widget = self.ui.mdiArea.addSubWindow(self.deliver_widget)
            self.deliver_widget.showMaximized()
        elif widget_number == 1:
            self.sale_widget = SaleWindow()
            self.ui.mdiArea.addSubWindow(self.sale_widget)
            self.sale_widget.showMaximized()

        elif widget_number == 2:
            self.drugs_widget = AllDrugsWindow()
            self.ui.mdiArea.addSubWindow(self.drugs_widget)
            self.drugs_widget.showMaximized()

        elif widget_number == 3:
            self.delivers_widget = AllDeliversWindow(self.ui.mdiArea)
            self.ui.mdiArea.addSubWindow(self.delivers_widget)
            self.delivers_widget.showMaximized()
        elif widget_number == 4:
            self.sales_widget = AllSalesWindow(self.ui.mdiArea)
            self.ui.mdiArea.addSubWindow(self.sales_widget)
            self.sales_widget.showMaximized()
        elif widget_number == 5:
            self.patients_widget = AllPatientsWindow()
            self.ui.mdiArea.addSubWindow(self.patients_widget)
            self.patients_widget.showMaximized()
        elif widget_number == 6:
            self.distributors_widget = AllDistributorsWindow()
            self.ui.mdiArea.addSubWindow(self.distributors_widget)
            self.distributors_widget.showMaximized()
        elif widget_number == 7:
            self.medorg_widget = AllMedorgWindow()
            self.ui.mdiArea.addSubWindow(self.medorg_widget)
            self.medorg_widget.showMaximized()
        elif widget_number == 8:
            self.doctors_widget = AllDoctorsWindow()
            self.doctors_widget = self.ui.mdiArea.addSubWindow(self.doctors_widget)
            self.doctors_widget.showMaximized()
        elif widget_number == 9:
            self.manufacters_widget = AllManufactersWindow()
            self.manufacters_widget = self.ui.mdiArea.addSubWindow(self.manufacters_widget)
            self.manufacters_widget.showMaximized()
            # QObject.connect(self.manufacters_widget, SIGNAL("closed()"), self.ui.mdiArea.removeSubWindow)

        elif widget_number == 10:
            self.ills_widget = AllIllsWindow()
            self.ills_widget = self.ui.mdiArea.addSubWindow(self.ills_widget)
            self.ills_widget.showMaximized()
        elif widget_number == 11:
            self.recipes_widget = AllRecipesWindow()
            self.recipes_widget = self.ui.mdiArea.addSubWindow(self.recipes_widget)
            self.recipes_widget.showMaximized()
示例#24
0
    def __init__(self):
        # Init the base class
        QMainWindow.__init__(self)

        self._settings = load_settings(Config.DEFAULT_SETTINGS)

        # Init the processed .ui file
        self._ui = Ui_MainWindow()
        self._ui.setupUi(self)
        self.setWindowTitle("TradeSkillMaster Application r{}".format(Config.CURRENT_VERSION))

        # connect signals / slots
        self._ui.addon_status_table.doubleClicked.connect(self._addon_status_table_clicked)
        self._ui.backup_status_table.doubleClicked.connect(self._backup_status_table_clicked)
        self._ui.settings_button.clicked.connect(self.settings_button_clicked.emit)
        self._ui.accounts_dropdown.activated['QString'].connect(self.accounts_dropdown_changed)
        self._ui.realm_dropdown.activated['QString'].connect(self.realm_dropdown_changed)
        self._ui.export_button.clicked.connect(self.export_button_clicked)
        self._ui.help_button.setProperty("url", "http://tradeskillmaster.com/site/getting-help")
        self._ui.help_button.clicked.connect(self._link_button_clicked)
        self._ui.premium_button.setProperty("url", "http://tradeskillmaster.com/premium")
        self._ui.premium_button.clicked.connect(self._link_button_clicked)
        self._ui.logo_button.setProperty("url", "http://tradeskillmaster.com")
        self._ui.logo_button.clicked.connect(self._link_button_clicked)
        self._ui.twitter_button.setProperty("url", "http://twitter.com/TSMAddon")
        self._ui.twitter_button.clicked.connect(self._link_button_clicked)

        # Apply the stylesheet
        file = QFile(":/resources/main_window.css")
        file.open(QIODevice.ReadOnly)
        data = str(file.readAll(), encoding="ascii")
        self.setStyleSheet(data)

        # set properties which are necessary for tweaking the style
        self._ui.help_button.setProperty("id", "premiumButton")
        self._ui.premium_button.setProperty("id", "premiumButton")
        self._ui.header_text.setProperty("id", "headerText")

        # stylesheet tweaks for things which don't work when put into the .css for some unknown reason
        self._ui.accounting_tab.setStyleSheet("QCheckBox:disabled { color : #666; } QCheckBox { color : white; }");

        self._sync_status_table_model = TableModel(self, ['Region/Realm', 'AuctionDB', 'Great Deals', 'Last Updated'])
        self._ui.sync_status_table.setModel(self._sync_status_table_model)

        self._addon_status_table_model = TableModel(self, ['Name', 'Version', 'Status'])
        self._ui.addon_status_table.setModel(self._addon_status_table_model)

        self._backup_status_table_model = TableModel(self, ['System ID', 'Account', 'Timestamp', 'Sync Status'])
        self._ui.backup_status_table.setModel(self._backup_status_table_model)

        self._accounting_info = {}
        self._accounting_current_account = ""
        self._accounting_current_realm = ""

        if Config.IS_WINDOWS:
            # create the system tray icon / menu
            self._tray_icon = QSystemTrayIcon(QIcon(":/resources/logo.png"), self)
            self._tray_icon.setToolTip("TradeSkillMaster Application r{}".format(Config.CURRENT_VERSION))
            self._tray_icon.activated.connect(self._icon_activated)
            tray_icon_menu = QMenu(self)
            restore_action = QAction("Restore", tray_icon_menu)
            restore_action.triggered.connect(self._restore_from_tray)
            tray_icon_menu.addAction(restore_action)
            tray_icon_menu.addSeparator()
            quit_action = QAction("Quit", tray_icon_menu)
            quit_action.triggered.connect(self.close)
            tray_icon_menu.addAction(quit_action)
            self._tray_icon.setContextMenu(tray_icon_menu)
            self._tray_icon.hide()
示例#25
0
class LpdFemGuiMainWindow(QtGui.QMainWindow):

    messageSignal = QtCore.pyqtSignal(object)
    runStateSignal = QtCore.pyqtSignal()
    run_status_signal = QtCore.pyqtSignal(object)
    powerStatusSignal = QtCore.pyqtSignal(object)

    def __init__(self, app_main):

        # Create main window UI

        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.app_main = app_main

        self.asyncCmd = None
        self.asyncCmdRunning = False

        # Create helper objects to manage main window tabs
        self.daqTab = LpdFemGuiMainDaqTab(app_main, self)
        self.pwrTab = LpdFemGuiMainPowerTab(app_main, self)
        self.configTab = LpdFemGuiMainConfigTab(app_main, self)
        self.evrTab = LpdFemGuiMainEvrTab(app_main, self)
        self.testTab = LpdFemGuiMainTestTab(app_main, self)
        self.ui.operatorEdit.text()

        if (self.app_main.asic_testing_enabled):
            pass
        else:
            # ASIC testing disabled, remove test tab
            testIdx = self.ui.verticalTabWidget.indexOf(self.ui.testTab)
            self.ui.verticalTabWidget.removeTab(testIdx)

        # Initialise default fields based on app_main object
        self.ui.connectAddr.setText(self.app_main.getCachedParam('femAddr'))
        self.ui.connectPort.setText(
            str(self.app_main.getCachedParam('femPort')))

        # Create a status bar with a progress bar
        self.createStatusBar("Not connected")

        # Connect signals and slots
        QtCore.QObject.connect(self.ui.connectButton,
                               QtCore.SIGNAL("clicked()"),
                               self.deviceConnectToggle)
        self.connect(self.ui.actionQuit, QtCore.SIGNAL('triggered()'),
                     self.quitApplication)

        # Connect msgRecv function to message signal to allow other non-GUI threads to print messages
        self.messageSignal.connect(self.msgRecv)

        # Connect runStateUpdate function to signal to allow other non-GUI threads to push state updates
        self.runStateSignal.connect(self.runStateUpdate)

        # Connect run status update function to signal to data recevier to push updates
        self.run_status_signal.connect(self.daqTab.runStatusUpdate)

        # Connect power status update function to signal
        self.powerStatusSignal.connect(self.pwrTab.powerStatusUpdateDisplay)

    def msgRecv(self, message):

        self.msgPrint(message)

    def runStateUpdate(self):

        self.daqTab.runStateUpdate(self.app_main.device_state)
        self.updateEnabledWidgets()

    def executeAsyncCmd(self, message, cmdHandler, completionHandler):

        if self.asyncCmdRunning == True:
            ret = QtGui.QMessageBox.critical(
                self, "System busy",
                "Please wait for the current operation to complete")
        else:
            self.asyncCmd = AsyncExecutionThread(cmdHandler,
                                                 self.completeAsyncCmd)
            self.asyncCompletion = completionHandler
            self.msgPrint(message)
            self.statusBar().showMessage(self.tr(message))
            self.progressBar.show()
            self.progressBar.setRange(0, 0)
            self.asyncCmdRunning = True
            self.asyncCmd.start()

    def completeAsyncCmd(self):

        self.asyncCompletion()
        self.progressBar.hide()
        self.statusBar().showMessage("Done")
        self.asyncCmdRunning = False

    def updateEnabledWidgets(self):

        if self.app_main.device_state == LpdFemState.DeviceDisconnected:

            self.ui.configGroupBox.setEnabled(False)
            self.ui.operateGroupBox.setEnabled(False)

        elif self.app_main.device_state == LpdFemState.DeviceIdle:

            self.ui.configGroupBox.setEnabled(True)
            self.ui.operateGroupBox.setEnabled(True)
            self.ui.configBtn.setEnabled(True)
            self.ui.runBtn.setEnabled(False)
            self.ui.stopBtn.setEnabled(False)

        elif self.app_main.device_state == LpdFemState.DeviceConfiguring:

            self.ui.configGroupBox.setEnabled(True)
            self.ui.operateGroupBox.setEnabled(True)
            self.ui.configBtn.setEnabled(False)
            self.ui.runBtn.setEnabled(False)
            self.ui.stopBtn.setEnabled(False)

        elif self.app_main.device_state == LpdFemState.DeviceReady:

            self.ui.configGroupBox.setEnabled(True)
            self.ui.operateGroupBox.setEnabled(True)
            self.ui.configBtn.setEnabled(True)
            self.ui.runBtn.setEnabled(True)
            self.ui.stopBtn.setEnabled(False)

        elif self.app_main.device_state == LpdFemState.DeviceRunning:

            self.ui.configGroupBox.setEnabled(True)
            self.ui.operateGroupBox.setEnabled(True)
            self.ui.configBtn.setEnabled(False)
            self.ui.runBtn.setEnabled(False)
            self.ui.stopBtn.setEnabled(True)

        self.daqTab.updateEnabledWidgets()
        self.pwrTab.updateEnabledWidgets()
        self.evrTab.updateEnabledWidgets()

    def createStatusBar(self, defaultMessage):
        sb = QtGui.QStatusBar()
        sb.setFixedHeight(18)
        self.setStatusBar(sb)
        self.statusBar().showMessage(self.tr(defaultMessage))
        self.progressBar = QtGui.QProgressBar(self.statusBar())
        self.statusBar().addPermanentWidget(self.progressBar)
        self.progressBar.hide()

    def deviceConnectToggle(self):

        if self.app_main.device_state == LpdFemState.DeviceDisconnected:

            # Extract address and port from GUI fields and validate
            deviceAddress = str(self.ui.connectAddr.text())
            devicePort = str(self.ui.connectPort.text())
            if not validIpAddress(deviceAddress) or not validPort(devicePort):
                ret = QtGui.QMessageBox.critical(
                    self, "Connection error",
                    "Please enter a valid address and port")
                return

            self.app_main.setCachedParam('femAddress', deviceAddress)
            self.app_main.setCachedParam('femPort', devicePort)

            self.ui.connectButton.setEnabled(False)
            cmdMsg = "Connecting to LPD device at address %s port %s ..." % (
                deviceAddress, devicePort)
            self.executeAsyncCmd(
                cmdMsg,
                partial(self.app_main.deviceConnect, deviceAddress,
                        devicePort), self.connectDone)
        else:
            self.app_main.deviceDisconnect()
            self.msgPrint("Device disconnected")
            self.statusBar().showMessage(self.tr("Not connected"))
            self.ui.connectStatus.setText("NO")
            self.ui.connectButton.setText("Connect")
            self.ui.lvStatus.setText("Unknown")
            self.ui.hvStatus.setText("Unknown")

        self.updateEnabledWidgets()

    def connectDone(self):

        self.progressBar.hide()
        self.ui.connectButton.setEnabled(True)
        # Toggle button text according to state
        if self.app_main.device_state != LpdFemState.DeviceDisconnected:

            self.msgPrint("Connected to device OK")
            self.statusBar().showMessage(self.tr("Connected to device"))
            self.ui.connectButton.setText("Disconnect")
            self.ui.connectStatus.setText("YES")
            self.app_main.femConfigGet()
            self.configTab.showConfig()

            self.app_main.pwr_card.statusUpdate()
            self.pwrTab.lvEnableToggleDone()
            self.pwrTab.hvEnableToggleDone()

            self.ui.configGroupBox.setEnabled(True)
            self.ui.operateGroupBox.setEnabled(True)

        else:
            self.statusBar().showMessage(self.tr("Not connected"))
            self.msgPrint(self.app_main.device_err_string)

            self.ui.connectButton.setText("Connect")
            self.ui.connectStatus.setText("NO")
            self.ui.lvStatus.setText("Unknown")
            self.ui.hvStatus.setText("Unknown")

            self.ui.configGroupBox.setEnabled(False)
            self.ui.operateGroupBox.setEnabled(False)

        self.updateEnabledWidgets()

    def msgPrint(self, msg):

        self.ui.messageBox.appendPlainText(
            "%s %s" % (time.strftime("%H:%M:%S"), str(msg)))
        self.ui.messageBox.verticalScrollBar().setValue(
            self.ui.messageBox.verticalScrollBar().maximum())
        self.ui.messageBox.repaint()
        self.app_main.app.processEvents()

    def quitApplication(self):

        if self.app_main.device_state != LpdFemState.DeviceDisconnected:
            self.app_main.deviceDisconnect()

        self.app_main.cleanup()
        self.app_main.app.quit()

    def closeEvent(self, theCloseEvent):

        if self.app_main.device_state != LpdFemState.DeviceDisconnected:
            self.app_main.deviceDisconnect()

        self.app_main.cleanup()
        theCloseEvent.accept()