class MainWidget(QWidget):
    """
    MainWidget class
    Main widget for the main window

    """
    def __init__(self, parent):
        super(MainWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        self.load_button = QPushButton("Load data")
        self.load_button.clicked.connect(self.scrape_data)
        self.layout.addWidget(self.load_button)

        self.status_label = QLabel()
        self.layout.addWidget(self.status_label)

        self.list_widget = QListWidget()
        self.list_widget.itemClicked.connect(self.item_clicked)
        self.layout.addWidget(self.list_widget)

        # Load the data from the database
        self.load_data()

        self.setLayout(self.layout)

    def scrape_data(self):
        """
        Scrape the data and load it into the list widget

        """
        scrape_and_save()
        self.load_data()
        self.status_label.setText("Data loaded")

    def load_data(self):
        """
        Load the data from the database into the list widget

        """
        self.list_widget.clear()
        data = Database.load_data_from_db()
        for item in data:
            self.list_widget.addItem(item.date + " : " + item.title + " - " +
                                     item.image)

    def item_clicked(self, item):
        """
        When a user clicks on the item in the list widget get the url for the
        item image and open it in the browser
        :param item: List widget item

        """
        text = item.text()
        image = text.split(' - ')
        image = image[1]
        import webbrowser
        webbrowser.open(image)
Пример #2
0
class NapalmInterfaces(QWidget):
    
    napalm_actions = (
    'Interfaces',
    'Interface IP',
    'Interfaces counters',
    )

    @update_paths
    def __init__(self, node, controller):
        super().__init__()
        self.node = node

        action_label = QLabel('Action')
        object_label = QLabel('Object')
        
        self.object_list = QListWidget()
        self.object_list.setSortingEnabled(True)
        self.object_list.itemSelectionChanged.connect(self.text_update)        
        
        self.action_list = QListWidget()
        self.action_list.setSortingEnabled(True)
        self.action_list.itemSelectionChanged.connect(self.text_update)
        self.action_list.addItems(self.napalm_actions)
        
        self.properties_edit = QConsoleEdit()
        self.properties_edit.setMinimumSize(300, 300)

        layout = QGridLayout()
        layout.addWidget(object_label, 0, 0)
        layout.addWidget(self.object_list, 1, 0)
        layout.addWidget(action_label, 0, 1)
        layout.addWidget(self.action_list, 1, 1)
        layout.addWidget(self.properties_edit, 2, 0, 1, 2)
        self.setLayout(layout)
        
    def update(self):
        self.object_list.clear()
        if 'Interfaces' in self.node.napalm_data:
            self.object_list.addItems(self.node.napalm_data['Interfaces'])
            
    def text_update(self):
        action = self.action_list.currentItem()
        object = self.object_list.currentItem()
        
        if action and object:
            self.properties_edit.clear()
            # we display a dictionnary with the following format:
            # property1: value1
            # property2: value2
            
            action, object = action.text(), object.text()
            value = str_dict(self.node.napalm_data[action][object])                
            self.properties_edit.insertPlainText(value)
                        
Пример #3
0
class MetricsWindowTab(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.name = self.tr("Metrics Window")

        self.inputTextLabel = QLabel(self.tr("Default text:"), self)
        self.inputTextList = QListWidget(self)
        self.inputTextList.setDragDropMode(QAbstractItemView.InternalMove)
        self.addItemButton = QPushButton("+", self)
        self.addItemButton.clicked.connect(self.addItem)
        self.removeItemButton = QPushButton("−", self)
        self.removeItemButton.clicked.connect(self.removeItem)

        layout = QGridLayout(self)
        l = 0
        layout.addWidget(self.inputTextLabel, l, 0, 1, 3)
        l += 1
        layout.addWidget(self.inputTextList, l, 0, 1, 3)
        l += 1
        layout.addWidget(self.addItemButton, l, 0)
        layout.addWidget(self.removeItemButton, l, 1)
        self.setLayout(layout)

        self.readSettings()

    def addItem(self):
        item = QListWidgetItem(self.inputTextList)
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self.inputTextList.setCurrentItem(item)
        self.inputTextList.editItem(item)
        self.removeItemButton.setEnabled(True)

    def removeItem(self):
        i = self.inputTextList.currentRow()
        self.inputTextList.takeItem(i)
        if not self.inputTextList.count():
            self.removeItemButton.setEnabled(False)

    def readSettings(self):
        self.inputTextList.clear()
        entries = settings.metricsWindowComboBoxItems()
        for entry in entries:
            item = QListWidgetItem(entry, self.inputTextList)
            item.setFlags(item.flags() | Qt.ItemIsEditable)
        if not len(entries):
            self.removeItemButton.setEnabled(False)

    def writeSettings(self):
        entries = []
        for i in range(self.inputTextList.count()):
            item = self.inputTextList.item(i)
            entries.append(item.text())
        settings.setMetricsWindowComboBoxItems(entries)
Пример #4
0
class AddFriendDialog(QDialog):
   def __init__(self, client_socket):
      super().__init__()
      self.client_socket = client_socket 
      self.client_socket.recv_user_search.connect(self.recvUserSearch)
      self.selected_user = None
      self.initUI()

   def initUI(self):
      self.grid = QGridLayout(self)

      self.search_box_label = QLabel("Search:")
      self.grid.addWidget(self.search_box_label, 0, 0, 1, 1)

      self.search_box = QLineEdit()
      self.grid.addWidget(self.search_box, 0, 1, 1, 2)

      self.search_button = QPushButton("Search")
      self.search_button.pressed.connect(self.searchUser)
      self.grid.addWidget(self.search_button, 0, 3, 1, 1)

      self.search_result = QListWidget()
      self.grid.addWidget(self.search_result, 1, 0, 2, 2)

      #TODO get user avatars to work
      self.add_friend_button = QPushButton("Add Friend")
      self.add_friend_button.pressed.connect(self.addFriend)
      self.grid.addWidget(self.add_friend_button, 1, 2, 1, 2)

      self.cancel_button = QPushButton("Cancel")
      self.cancel_button.pressed.connect(self.cancel)
      self.grid.addWidget(self.cancel_button, 2, 2, 1, 2)

   def searchUser(self):
      self.client_socket.searchUser(self.search_box.text())

   def recvUserSearch(self, found_users):
      self.search_result.clear()
      for user in found_users:
         self.search_result.addItem(QListWidgetItem(user))

   def addFriend(self):
      self.selected_user = self.search_result.selectedItems()[0].text()
      config.friends[self.selected_user] = {}
      self.close()

   def cancel(self):
      self.close()
Пример #5
0
class LogWidget(QWidget):

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

        self.initUI()

        self.show()

    def initUI(self):

        self.btnclear = QPushButton("Clear messages", self)
        self.btnclear.clicked.connect(self._clearClicked)
        
        self.lwmessages = QListWidget(self)
        for _, msgtype, msgtext in Log.getLogMessages():
            self.addLogItem(msgtype, msgtext)

        self.hboxlayout = QHBoxLayout()
        self.hboxlayout.addWidget(self.btnclear)
        self.hboxlayout.addStretch()

        self.vboxlayout = QVBoxLayout()
        self.vboxlayout.addLayout(self.hboxlayout)
        self.vboxlayout.addWidget(self.lwmessages)

        self.setLayout(self.vboxlayout)

        # Make sure this widget listens to new logevents
        Log.setNewMessageCallBack(self._newMessageAddedToLog)

    def _clearClicked(self):
        self.lwmessages.clear()
        Log.clearMessages()

    def _newMessageAddedToLog(self, msgtype, msgtext):
        self.addLogItem(msgtype, msgtext)

    def addLogItem(self, msgtype, msgtext):
        if msgtype == Log.INFO:
            icon = QIcon('images/information.png')
        elif msgtype == Log.WARNING:
            icon = QIcon('images/warning.png')
        else:
            icon = QIcon('images/error.png')
        item = QListWidgetItem(icon, msgtext)
        self.lwmessages.addItem(item)
Пример #6
0
class SessionManager(QMainWindow):
    def __init__(self, parent=None):
        QListWidget.__init__(self, parent)
        self.setWindowTitle(tr("Saved Sessions"))
        self.setWindowFlags(Qt.Dialog)
        hideAction = QAction(self)
        hideAction.setShortcuts(["Esc", "Ctrl+W"])
        hideAction.triggered.connect(self.hide)
        self.addAction(hideAction)
        self.sessionList = QListWidget(self)
        self.sessionList.itemActivated.connect(self.loadSession)
        self.setCentralWidget(self.sessionList)
        self.toolBar = QToolBar(self)
        self.toolBar.setMovable(False)
        self.toolBar.setContextMenuPolicy(Qt.CustomContextMenu)
        self.addToolBar(Qt.BottomToolBarArea, self.toolBar)
        self.loadButton = QPushButton(tr("&Load"), self)
        self.loadButton.clicked.connect(lambda: self.loadSession(self.sessionList.currentItem()))
        self.toolBar.addWidget(self.loadButton)
        self.saveButton = QPushButton(tr("&Save"), self)
        self.saveButton.clicked.connect(saveSessionManually)
        self.saveButton.clicked.connect(self.refresh)
        self.toolBar.addWidget(self.saveButton)
        deleteAction = QAction(self)
        deleteAction.setShortcut("Del")
        deleteAction.triggered.connect(self.delete)
        self.addAction(deleteAction)
    def refresh(self):
        self.sessionList.clear()
        if os.path.exists(settings.session_folder):
            sessions = os.listdir(settings.session_folder)
            for session in sessions:
                self.sessionList.addItem(session)
    def delete(self):
        if self.sessionList.hasFocus():
            try: os.remove(os.path.join(settings.session_folder, self.sessionList.currentItem().text()))
            except: pass
            self.refresh()
    def show(self):
        self.refresh()
        QMainWindow.show(self)
    def loadSession(self, item):
        if os.path.exists(settings.session_folder):
            loadSession(os.path.join(settings.session_folder, item.text()))
        self.hide()
Пример #7
0
class TabGroup(QWidget, itab_item.ITabItem):

    def __init__(self, project, name, actions):
        super(TabGroup, self).__init__()
        vbox = QVBoxLayout(self)
        self.actions = actions
        self.project = project
        self.ID = self.project
        self.name = name
        self.tabs = []
        self.listWidget = QListWidget()
        hbox = QHBoxLayout()
        btnExpand = QPushButton(_translate("TabGroup", "Expand this Files"))
        btnExpandAll = QPushButton(_translate("TabGroup", "Expand all Groups"))
        hbox.addWidget(btnExpandAll)
        hbox.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Expanding))
        hbox.addWidget(btnExpand)
        vbox.addLayout(hbox)
        vbox.addWidget(self.listWidget)

        btnExpand.clicked['bool'].connect(self.expand_this)
        btnExpandAll.clicked['bool'].connect(self.actions.deactivate_tabs_groups)

    def add_widget(self, widget):
        self.tabs.append(widget)
        self.listWidget.addItem(widget.ID)

    def expand_this(self):
        self.actions.group_tabs_together()
        for tab in self.tabs:
            tabName = file_manager.get_basename(tab.ID)
            self.actions.ide.mainContainer.add_tab(tab, tabName)
        index = self.actions.ide.mainContainer._tabMain.indexOf(self)
        self.actions.ide.mainContainer._tabMain.removeTab(index)
        self.tabs = []
        self.listWidget.clear()

    def only_expand(self):
        for tab in self.tabs:
            tabName = file_manager.get_basename(tab.ID)
            self.actions.ide.mainContainer.add_tab(tab, tabName)
        index = self.actions.ide.mainContainer._tabMain.indexOf(self)
        self.actions.ide.mainContainer._tabMain.removeTab(index)
        self.tabs = []
        self.listWidget.clear()
Пример #8
0
class AdremoverSettingsPanel(SettingsPanel):
    def __init__(self, parent=None):
        super(AdremoverSettingsPanel, self).__init__(parent)

        filterEntryRow = custom_widgets.LineEditRow(tr("Add filter:"), self)
        self.filterEntry = filterEntryRow.lineEdit
        self.filterEntry.returnPressed.connect(self.addFilter)
        self.layout().addWidget(filterEntryRow)

        self.addFilterButton = QPushButton(tr("Add"))
        self.addFilterButton.clicked.connect(self.addFilter)
        filterEntryRow.layout().addWidget(self.addFilterButton)

        # Ad Remover filter list.
        self.filterList = QListWidget(self)
        self.layout().addWidget(self.filterList)

        self.removeFilterButton = QPushButton(tr("Remove"))
        self.removeFilterButton.clicked.connect(lambda: self.removeFilter(True))
        self.layout().addWidget(self.removeFilterButton)

        self.removeAction = QAction(self)
        self.removeAction.setShortcut("Del")
        self.removeAction.triggered.connect(self.removeFilter)
        self.addAction(self.removeAction)

    def removeFilter(self, forceFocus=False):
        if self.filterList.hasFocus() or forceFocus:
            self.filterList.takeItem(self.filterList.row(self.filterList.currentItem()))

    def addFilter(self):
        self.filterList.addItem(self.filterEntry.text())
        self.filterEntry.clear()

    def loadSettings(self):
        settings.load_adremover_filters()
        self.filterList.clear()
        for f in settings.adremover_filters:
            self.filterList.addItem(f)

    def saveSettings(self):
        settings.adremover_filters = [self.filterList.item(f).text() for f in range(0, self.filterList.count())]
        settings.save_adremover_filters()
Пример #9
0
class JavaScriptExceptionsPanel(SettingsPanel):
    def __init__(self, parent=None):
        super(JavaScriptExceptionsPanel, self).__init__(parent)

        domainEntryRow = custom_widgets.LineEditRow(tr("Add domain:"), self)
        self.domainEntry = domainEntryRow.lineEdit
        self.domainEntry.returnPressed.connect(self.addDomain)
        self.layout().addWidget(domainEntryRow)

        self.addDomainButton = QPushButton(tr("Add"))
        self.addDomainButton.clicked.connect(self.addDomain)
        domainEntryRow.layout().addWidget(self.addDomainButton)

        self.domainList = QListWidget(self)
        self.layout().addWidget(self.domainList)

        self.removeDomainButton = QPushButton(tr("Remove"))
        self.removeDomainButton.clicked.connect(lambda: self.removeDomain(True))
        self.layout().addWidget(self.removeDomainButton)

        self.removeAction = QAction(self)
        self.removeAction.setShortcut("Del")
        self.removeAction.triggered.connect(self.removeDomain)
        self.addAction(self.removeAction)

    def removeDomain(self, forceFocus=False):
        if self.domainList.hasFocus() or forceFocus:
            self.domainList.takeItem(self.domainList.row(self.domainList.currentItem()))

    def addDomain(self):
        self.domainList.addItem(self.domainEntry.text())
        self.domainEntry.clear()

    def loadSettings(self):
        settings.js_exceptions = settings.setting_to_list("content/JavaScriptExceptions")
        self.domainList.clear()
        for f in settings.js_exceptions:
            self.domainList.addItem(f)

    def saveSettings(self):
        settings.js_exceptions = [self.domainList.item(f).text() for f in range(0, self.domainList.count())]
        settings.settings.setValue("content/JavaScriptExceptions", settings.js_exceptions)
        settings.settings.sync()
Пример #10
0
class BWPassengerWindow(QMdiSubWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setBaseSize(400, 400)

        self.centralwidget = QWidget(self)
        self.setWidget(self.centralwidget)

        layout = QHBoxLayout(self.centralwidget)
        self.passengerlist = QListWidget(self.centralwidget)
        layout.addWidget(self.passengerlist)
        self.setWindowTitle("Passengers")

    def reset(self):
        self.passengerlist.clearSelection()
        self.passengerlist.clear()

    def add_passenger(self, passenger_name, passenger_id):
        item = BWEntityEntry(passenger_id,
                             passenger_name)
        self.passengerlist.addItem(item)

    def set_title(self, entityname):
        self.setWindowTitle("Passengers - {0}".format(entityname))
Пример #11
0
class GstMediaSettings(SettingsSection):

    Name = 'Media Settings'

    def __init__(self, size, cue=None, parent=None):
        super().__init__(size, cue=cue, parent=parent)
        self._pipe = ''
        self._conf = {}
        self._check = False

        self.glayout = QGridLayout(self)

        self.listWidget = QListWidget(self)
        self.glayout.addWidget(self.listWidget, 0, 0)

        self.pipeButton = QPushButton('Change Pipe', self)
        self.glayout.addWidget(self.pipeButton, 1, 0)

        self.elements = QStackedWidget(self)
        self.glayout.addWidget(self.elements, 0, 1, 2, 1)

        self.glayout.setColumnStretch(0, 2)
        self.glayout.setColumnStretch(1, 5)

        self.listWidget.currentItemChanged.connect(self.__change_page)
        self.pipeButton.clicked.connect(self.__edit_pipe)

    def set_configuration(self, conf):
        # Get the media section of the cue configuration
        if conf is not None:
            conf = conf.get('media', {})

            # Activate the layout, so we can get the right widgets size
            self.glayout.activate()

            # Create a local copy of the configuration
            self._conf = deepcopy(conf)

            # Create the widgets
            sections = sections_by_element_name()
            for element in conf.get('pipe', '').split('!'):
                widget = sections.get(element)

                if widget is not None:
                    widget = widget(self.elements.size(), element, self)
                    widget.set_configuration(self._conf['elements'])
                    self.elements.addWidget(widget)

                    item = QListWidgetItem(widget.NAME)
                    self.listWidget.addItem(item)

            self.listWidget.setCurrentRow(0)

    def get_configuration(self):
        conf = {'elements': {}}

        for el in self.elements.children():
            if isinstance(el, SettingsSection):
                conf['elements'].update(el.get_configuration())

        # If in check mode the pipeline is not returned
        if not self._check:
            conf['pipe'] = self._conf['pipe']

        return {'media': conf}

    def enable_check(self, enable):
        self._check = enable
        for element in self.elements.children():
            if isinstance(element, SettingsSection):
                element.enable_check(enable)

    def __change_page(self, current, previous):
        if not current:
            current = previous

        self.elements.setCurrentIndex(self.listWidget.row(current))

    def __edit_pipe(self):
        # Backup the settings
        self._conf.update(self.get_configuration()['media'])

        # Show the dialog
        dialog = GstPipeEdit(self._conf.get('pipe', ''), parent=self)

        if dialog.exec_() == dialog.Accepted:
            # Reset the view
            for _ in range(self.elements.count()):
                self.elements.removeWidget(self.elements.widget(0))
            self.listWidget.clear()

            # Reload with the new pipeline
            self._conf['pipe'] = dialog.get_pipe()

            self.set_configuration({'media': self._conf})
            self.enable_check(self._check)
Пример #12
0
class StartWindow(QWidget):
    def __init__(self, model=None):
        super().__init__()  # zwraca klase rodzica i wywoluje jego konstruktor
        self.model = model
        self.interface()

    def interface(self):

        #1-liniowe pola edycyjne
        self.featuresEdt = QLineEdit()
        self.featuresEdt.setText("1")
        self.sizeSetEdt = QLineEdit()
        self.sizeSetEdt.setText("10")
        self.paramsEdt = QLineEdit()
        self.paramsEdt.setText("1")

        # przyciski
        self.addFeaturesBtn = QPushButton("&AddFeatures", self)
        self.createSetBtn = QPushButton("&Create", self)
        self.addParamsBtn = QPushButton("Add&Params", self)
        self.findParams = QPushButton("&FindParams", self)
        self.resetBtn = QPushButton("&Reset", self)

        self.addFeaturesBtn.clicked.connect(self.addFeaturesClick)
        self.createSetBtn.clicked.connect(self.createSetClick)
        self.addParamsBtn.clicked.connect(self.addParamsClick)
        self.findParams.clicked.connect(self.findParamsClick)
        self.resetBtn.clicked.connect(self.resetClick)

        # etykiety
        self.featuresLabel = QLabel("Features: ", self)
        self.setLabel = QLabel("Set: ", self)
        self.paramsLabel = QLabel("Params: ", self)
        self.matchingLabel = QLabel("Maching: ", self)

        # ListWidget
        self.featuresListWidget = QListWidget()
        self.setWidget = QListWidget()
        self.paramsListWidget = QListWidget()
        self.findParamsListWidget = QListWidget()

        # uklad tabelaryczny:
        self.tab_layout = QGridLayout()

        self.tab_layout.addWidget(self.featuresEdt, 0, 0)
        self.tab_layout.addWidget(self.sizeSetEdt, 0, 1)
        self.tab_layout.addWidget(self.paramsEdt, 0, 2)
        self.tab_layout.addWidget(self.resetBtn, 0, 3)

        self.tab_layout.addWidget(self.addFeaturesBtn, 1, 0)
        self.tab_layout.addWidget(self.createSetBtn, 1, 1)
        self.tab_layout.addWidget(self.addParamsBtn, 1, 2)
        self.tab_layout.addWidget(self.findParams, 1, 3)

        self.tab_layout.addWidget(self.featuresLabel, 2, 0)
        self.tab_layout.addWidget(self.setLabel, 2, 1)
        self.tab_layout.addWidget(self.paramsLabel, 2, 2)
        self.tab_layout.addWidget(self.matchingLabel, 2, 3)

        self.tab_layout.addWidget(self.featuresListWidget, 3, 0)
        self.tab_layout.addWidget(self.setWidget, 3, 1)
        self.tab_layout.addWidget(self.paramsListWidget, 3, 2)
        self.tab_layout.addWidget(self.findParamsListWidget, 3, 3)

        # przypisanie utworzonego ukladu do okna

        self.setLayout(self.tab_layout)

        self.showMaximized()
        self.setWindowTitle("Projekt - dopasowanie zbiorow")
        self.show()

    def addFeaturesClick(self):
        self.model.listoffeatures.addToList(self.featuresEdt.text())
        #print(self.model.listoffeatures.list)
        l = len(self.model.listoffeatures.list) - 1
        self.featuresListWidget.insertItem(l,
                                           self.model.listoffeatures.list[-1])

    def createSetClick(self):
        self.setWidget.clear()
        self.model.set.createSet(int(self.sizeSetEdt.text()),
                                 model.listoffeatures.list)
        print(model.set.set)
        for a in model.set.set:
            self.setWidget.addItem(str(a))

    def addParamsClick(self):

        self.model.listOfParams.addToList(self.paramsEdt.text())
        # print(self.model.listoffeatures.list)
        l = len(self.model.listOfParams.list) - 1
        self.paramsListWidget.insertItem(l, self.model.listOfParams.list[-1])
        print(self.model.listOfParams.list)

    def findParamsClick(self):
        self.model.set.findParams(self.model.listOfParams.list)
        for i, a in enumerate(self.model.set.listofResults):
            self.findParamsListWidget.insertItem(i, str(a))

    def resetClick(self):
        self.model.resetmodel()
        self.clearLayout(self.tab_layout)

    def clearLayout(self, layout):
        self.featuresListWidget.clear()
        self.setWidget.clear()
        self.paramsListWidget.clear()
        self.findParamsListWidget.clear()
Пример #13
0
class QuestionManagerDlg(TopicManagerDlg):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(QuestionManagerDlg, cls).__new__(cls, *args, **kwargs)
        return cls._instance

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

        self.btnAddL = QPushButton('Add')
        self.btnRemoveL = QPushButton('Remove')
        self.btnRemoveL.setEnabled(False)
        self.LangBox.addWidget(self.btnAddL)
        self.LangBox.addWidget(self.btnRemoveL)

        self.btnAddT = QPushButton('Add')
        self.btnRemoveT = QPushButton('Remove')
        self.btnRemoveT.setEnabled(False)
        self.topicBox.addWidget(self.btnAddT)
        self.topicBox.addWidget(self.btnRemoveT)

        lblQuestions = QLabel('Select a question.')
        self.lstQuestions = QListWidget()
        self.lstQuestions.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.btnRemoveQ = QPushButton('Remove')
        self.btnRemoveQ.setEnabled(False)

        _layout3 = QVBoxLayout()
        _layout3.addWidget(lblQuestions)
        _layout3.addWidget(self.lstQuestions)
        _layout3.addWidget(self.btnRemoveQ)

        self.layout.addLayout(_layout3)
        self.setLayout(self.layout)

        self.lstLangs.itemClicked.connect(self.selectLang)
        self.lstTopics.itemClicked.connect(self.selectTopic)
        self.lstQuestions.itemClicked.connect(self.onSelectQuestion)
        self.btnAddL.clicked.connect(self.onAddL)
        self.btnRemoveL.clicked.connect(self.onRemoveL)
        self.btnAddT.clicked.connect(self.onAddT)
        self.btnRemoveT.clicked.connect(self.onRemoveT)
        self.btnRemoveQ.clicked.connect(self.onRemoveQ)

    def selectLang(self, item):
        ''' show topics that are related with selected language.
        :param item: language
        :return: QListWidgetItem
        '''
        self.btnRemoveL.setEnabled(True)
        _lang = item.text()
        lang = session.query(Language).filter(Language.name == _lang).first()
        if not lang:
            return
        topics = lang.topics.all()
        self.lstTopics.clear()
        for topic in topics:
            item = QListWidgetItem()
            item.setText(topic.title)
            item.setStatusTip(str(topic.id))
            self.lstTopics.addItem(item)
        self.lstQuestions.clear()

    def selectTopic(self, item):
        self.btnRemoveT.setEnabled(True)
        _topic = item.text()
        topic = session.query(Topic).filter(Topic.title == _topic).first()
        questions = topic.questions.all()
        self.lstQuestions.clear()
        for q in questions:
            item = QListWidgetItem()
            item.setText(q.text)
            item.setStatusTip(str(q.id))
            self.lstQuestions.addItem(item)

    def onSelectQuestion(self, item):
        ''' Set the button 'Remove question' to enabled.
        '''
        self.btnRemoveQ.setEnabled(True)

    def onAddL(self):
        ''' Add new language.
        '''
        lang, ok = QInputDialog.getText(self, 'add language', 'Input language name')
        if ok and lang and lang.strip():
            if self.lstLangs.findItems(lang, Qt.MatchFixedString):
                QMessageBox.information(self, 'Error', '{} exists already.'.format(lang))
                return
            l = Language(name=lang)
            session.add(l)
            session.commit()
            item = QListWidgetItem()
            item.setText(l.name)
            item.setStatusTip(str(l.id))
            self.lstLangs.addItem(item)

    def onRemoveL(self):
        ''' remove selected langauge and realted topics and questions.
        '''
        answer = QMessageBox.question(self, 'Remove Language',
                                      "This operation will remove this language and it's topics.")
        if answer == QMessageBox.No:
            return
        row = self.lstLangs.currentRow()
        id = self.lstLangs.currentItem().statusTip()
        record = session.query(Language).filter(Language.id == id)
        if record:
            record.delete(synchronize_session=False)
            self.lstLangs.takeItem(row)
            self.lstTopics.clear()
            ts = session.query(Topic).filter(Topic.lang_id == id).all()
            for t in ts:
                qs = session.query(Question).filter(Question.topic_id == t.id).all()
                for q in qs:
                    session.delete(q)
                session.delete(t)
        session.commit()
        self.btnRemoveL.setEnabled(False)

    # @pyqtSlot(Topic)
    def _finishAddQuestions(self, t):
        item = QListWidgetItem()
        item.setText(t.title)
        item.setStatusTip(str(t.id))
        self.lstTopics.addItem(item)
        session.commit()
        print('finished')

    # @pyqtSlot(Question)
    def _appendQuestion(self, q):
        print('q: ', q)
        item = QListWidgetItem()
        item.setText(q.text)
        item.setStatusTip(str(q.id))
        self.lstQuestions.addItem(item)
        session.add(q)

    def onAddT(self):
        ''' Add new topic.
        '''
        lang = self.lstLangs.currentItem()
        if not lang:
            return
        lang = lang.text()
        url, ok = QInputDialog.getText(self, 'add topic', 'Input url for {}'.format(lang))
        if ok and lang and url and url.strip():
            try:
                thread = Worker(lang, url, self)
                thread.update.connect(self._appendQuestion)
                thread.finish.connect(self._finishAddQuestions)
                thread.start()
            except FileExistsError:
                QMessageBox.information(self, 'Error', 'This topic exists already.')
            except ValueError:
                QMessageBox.information(self, 'Error', 'cannot access the url.')

    def onRemoveT(self):
        answer = QMessageBox.question(self, 'Remove Topic', "This operation will remove this topic and it's questions.")
        if answer == QMessageBox.No:
            return
        row = self.lstTopics.currentRow()
        id = self.lstTopics.currentItem().statusTip()
        record = session.query(Topic).filter(Topic.id == id)
        if record:
            record.delete(synchronize_session=False)
            self.lstTopics.takeItem(row)
            self.lstQuestions.clear()
            qs = session.query(Question).filter(Question.topic_id == id).all()
            for q in qs:
                session.delete(q)
        session.commit()
        self.btnRemoveT.setEnabled(False)

    def onRemoveQ(self):
        ''' Remove a selected question from database.
        '''
        for item in self.lstQuestions.selectedItems():
            id = item.statusTip()
            self.lstQuestions.setCurrentItem(item)
            row = self.lstQuestions.currentRow()
            record = session.query(Question).filter(Question.id == id)
            if record:
                record.delete(synchronize_session=False)
                self.lstQuestions.takeItem(row)
        session.commit()
        self.btnRemoveQ.setEnabled(False)
Пример #14
0
class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        self.mutex = QMutex()
        self.fileCount = 0
        self.filenamesForWords = collections.defaultdict(set)
        self.commonWords = set()
        self.lock = QReadWriteLock()
        self.path = QDir.homePath()
        pathLabel = QLabel("Indexing path:")
        self.pathLabel = QLabel()
        self.pathLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.pathButton = QPushButton("Set &Path...")
        self.pathButton.setAutoDefault(False)
        findLabel = QLabel("&Find word:")
        self.findEdit = QLineEdit()
        findLabel.setBuddy(self.findEdit)
        commonWordsLabel = QLabel("&Common words:")
        self.commonWordsListWidget = QListWidget()
        commonWordsLabel.setBuddy(self.commonWordsListWidget)
        filesLabel = QLabel("Files containing the &word:")
        self.filesListWidget = QListWidget()
        filesLabel.setBuddy(self.filesListWidget)
        filesIndexedLabel = QLabel("Files indexed")
        self.filesIndexedLCD = QLCDNumber()
        self.filesIndexedLCD.setSegmentStyle(QLCDNumber.Flat)
        wordsIndexedLabel = QLabel("Words indexed")
        self.wordsIndexedLCD = QLCDNumber()
        self.wordsIndexedLCD.setSegmentStyle(QLCDNumber.Flat)
        commonWordsLCDLabel = QLabel("Common words")
        self.commonWordsLCD = QLCDNumber()
        self.commonWordsLCD.setSegmentStyle(QLCDNumber.Flat)
        self.statusLabel = QLabel("Click the 'Set Path' "
                                  "button to start indexing")
        self.statusLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)

        topLayout = QHBoxLayout()
        topLayout.addWidget(pathLabel)
        topLayout.addWidget(self.pathLabel, 1)
        topLayout.addWidget(self.pathButton)
        topLayout.addWidget(findLabel)
        topLayout.addWidget(self.findEdit, 1)
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(filesLabel)
        leftLayout.addWidget(self.filesListWidget)
        rightLayout = QVBoxLayout()
        rightLayout.addWidget(commonWordsLabel)
        rightLayout.addWidget(self.commonWordsListWidget)
        middleLayout = QHBoxLayout()
        middleLayout.addLayout(leftLayout, 1)
        middleLayout.addLayout(rightLayout)
        bottomLayout = QHBoxLayout()
        bottomLayout.addWidget(filesIndexedLabel)
        bottomLayout.addWidget(self.filesIndexedLCD)
        bottomLayout.addWidget(wordsIndexedLabel)
        bottomLayout.addWidget(self.wordsIndexedLCD)
        bottomLayout.addWidget(commonWordsLCDLabel)
        bottomLayout.addWidget(self.commonWordsLCD)
        bottomLayout.addStretch()
        layout = QVBoxLayout()
        layout.addLayout(topLayout)
        layout.addLayout(middleLayout)
        layout.addLayout(bottomLayout)
        layout.addWidget(self.statusLabel)
        self.setLayout(layout)

        self.walkers = []
        self.completed = []
        self.pathButton.clicked.connect(self.setPath)
        self.findEdit.returnPressed.connect(self.find)
        self.setWindowTitle("Page Indexer")

    def stopWalkers(self):
        for walker in self.walkers:
            if isAlive(walker) and walker.isRunning():
                walker.stop()
        for walker in self.walkers:
            if isAlive(walker) and walker.isRunning():
                walker.wait()
        self.walkers = []
        self.completed = []

    def setPath(self):
        self.stopWalkers()
        self.pathButton.setEnabled(False)
        path = QFileDialog.getExistingDirectory(self, "Choose a Path to Index",
                                                self.path)
        if not path:
            self.statusLabel.setText("Click the 'Set Path' "
                                     "button to start indexing")
            self.pathButton.setEnabled(True)
            return
        self.statusLabel.setText("Scanning directories...")
        QApplication.processEvents()  # Needed for Windows
        self.path = QDir.toNativeSeparators(path)
        self.findEdit.setFocus()
        self.pathLabel.setText(self.path)
        self.statusLabel.clear()
        self.filesListWidget.clear()
        self.fileCount = 0
        self.filenamesForWords = collections.defaultdict(set)
        self.commonWords = set()
        nofilesfound = True
        files = []
        index = 0
        for root, dirs, fnames in os.walk(str(self.path)):
            for name in [
                    name for name in fnames if name.endswith((".htm", ".html"))
            ]:
                files.append(os.path.join(root, name))
                if len(files) == 1000:
                    self.processFiles(index, files[:])
                    files = []
                    index += 1
                    nofilesfound = False
        if files:
            self.processFiles(index, files[:])
            nofilesfound = False
        if nofilesfound:
            self.finishedIndexing()
            self.statusLabel.setText("No HTML files found in the given path")

    def processFiles(self, index, files):
        thread = walker.Walker(index, self.lock, files, self.filenamesForWords,
                               self.commonWords, self)
        thread.indexed[str, int].connect(self.indexed)
        thread.finished[bool, int].connect(self.finished)
        thread.finished.connect(thread.deleteLater)
        self.walkers.append(thread)
        self.completed.append(False)
        thread.start()
        thread.wait(300)  # Needed for Windows

    def find(self):
        word = str(self.findEdit.text())
        if not word:
            try:
                self.mutex.lock()
                self.statusLabel.setText("Enter a word to find in files")
            finally:
                self.mutex.unlock()
            return
        try:
            self.mutex.lock()
            self.statusLabel.clear()
            self.filesListWidget.clear()
        finally:
            self.mutex.unlock()
        word = word.lower()
        if " " in word:
            word = word.split()[0]
        try:
            self.lock.lockForRead()
            found = word in self.commonWords
        finally:
            self.lock.unlock()
        if found:
            try:
                self.mutex.lock()
                self.statusLabel.setText("Common words like '{0}' "
                                         "are not indexed".format(word))
            finally:
                self.mutex.unlock()
            return
        try:
            self.lock.lockForRead()
            files = self.filenamesForWords.get(word, set()).copy()
        finally:
            self.lock.unlock()
        if not files:
            try:
                self.mutex.lock()
                self.statusLabel.setText("No indexed file contains "
                                         "the word '{0}'".format(word))
            finally:
                self.mutex.unlock()
            return
        files = [
            QDir.toNativeSeparators(name)
            for name in sorted(files, key=str.lower)
        ]
        try:
            self.mutex.lock()
            self.filesListWidget.addItems(files)
            self.statusLabel.setText(
                "{0} indexed files contain the word '{1}'".format(
                    len(files), word))
        finally:
            self.mutex.unlock()

    def indexed(self, fname, index):
        try:
            self.mutex.lock()
            self.statusLabel.setText(fname)
            self.fileCount += 1
            count = self.fileCount
        finally:
            self.mutex.unlock()
        if count % 25 == 0:
            try:
                self.lock.lockForRead()
                indexedWordCount = len(self.filenamesForWords)
                commonWordCount = len(self.commonWords)
            finally:
                self.lock.unlock()
            try:
                self.mutex.lock()
                self.filesIndexedLCD.display(count)
                self.wordsIndexedLCD.display(indexedWordCount)
                self.commonWordsLCD.display(commonWordCount)
            finally:
                self.mutex.unlock()
        elif count % 101 == 0:
            try:
                self.lock.lockForRead()
                words = self.commonWords.copy()
            finally:
                self.lock.unlock()
            try:
                self.mutex.lock()
                self.commonWordsListWidget.clear()
                self.commonWordsListWidget.addItems(sorted(words))
            finally:
                self.mutex.unlock()

    def finished(self, completed, index):
        done = False
        if self.walkers:
            self.completed[index] = True
            if all(self.completed):
                try:
                    self.mutex.lock()
                    self.statusLabel.setText("Finished")
                    done = True
                finally:
                    self.mutex.unlock()
        else:
            try:
                self.mutex.lock()
                self.statusLabel.setText("Finished")
                done = True
            finally:
                self.mutex.unlock()
        if done:
            self.finishedIndexing()

    def reject(self):
        if not all(self.completed):
            self.stopWalkers()
            self.finishedIndexing()
        else:
            self.accept()

    def closeEvent(self, event=None):
        self.stopWalkers()

    def finishedIndexing(self):
        self.filesIndexedLCD.display(self.fileCount)
        self.wordsIndexedLCD.display(len(self.filenamesForWords))
        self.commonWordsLCD.display(len(self.commonWords))
        self.pathButton.setEnabled(True)
        QApplication.processEvents()  # Needed for Windows
Пример #15
0
class MainWindow(QMainWindow):
    htmlReady = pyqtSignal(str)

    def __init__(self, app):
        QMainWindow.__init__(self)
        self.install_directory = os.getcwd()
        self.app = app
        self.book = None
        self.last_book = ""
        self.filename = ""
        self._part_is_new = False
        self.tread_running = False
        self.initTheme()
        self.createUi()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()
        self.text_edit.textChanged.connect(self.textChanged)

    def initTheme(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        self.theme = settings.value("theme", "Fusion")
        hilite_color = settings.value(
            "hiliteColor",
            self.palette().highlight().color().name())
        self.changeStyle(self.theme, hilite_color)

    def showEvent(self, event):
        if self.last_book:
            self.loadBook(self.last_book)

    def changeStyle(self, theme, hilite_color):
        self.theme = theme
        if theme == "DarkFusion":
            QApplication.setStyle(DarkFusion(hilite_color))
        else:
            QApplication.setStyle(QStyleFactory.create(theme))
            pal = self.app.palette()
            pal.setColor(QPalette.Highlight, QColor(hilite_color))
            self.app.setPalette(pal)

    def createUi(self):
        self.content = Expander("Content", ":/images/parts.svg")
        self.images = Expander("Images", ":/images/images.svg")
        self.settings = Expander("Settings", ":/images/settings.svg")

        self.setWindowTitle(QCoreApplication.applicationName() + " " +
                            QCoreApplication.applicationVersion())
        vbox = QVBoxLayout()
        vbox.addWidget(self.content)
        vbox.addWidget(self.images)
        vbox.addWidget(self.settings)
        vbox.addStretch()

        self.content_list = QListWidget()
        self.content_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        content_box = QVBoxLayout()
        content_box.addWidget(self.content_list)
        self.item_edit = QLineEdit()
        self.item_edit.setMaximumHeight(0)
        self.item_edit.editingFinished.connect(self.editItemFinished)
        self.item_anim = QPropertyAnimation(self.item_edit,
                                            "maximumHeight".encode("utf-8"))
        content_box.addWidget(self.item_edit)
        button_layout = QHBoxLayout()
        plus_button = FlatButton(":/images/plus.svg")
        self.edit_button = FlatButton(":/images/edit.svg")
        self.trash_button = FlatButton(":/images/trash.svg")
        self.up_button = FlatButton(":/images/up.svg")
        self.down_button = FlatButton(":/images/down.svg")
        self.trash_button.enabled = False
        self.up_button.enabled = False
        self.down_button.enabled = False
        button_layout.addWidget(plus_button)
        button_layout.addWidget(self.up_button)
        button_layout.addWidget(self.down_button)
        button_layout.addWidget(self.edit_button)
        button_layout.addWidget(self.trash_button)
        content_box.addLayout(button_layout)
        self.content.addLayout(content_box)
        plus_button.clicked.connect(self.addPart)
        self.trash_button.clicked.connect(self.dropPart)
        self.up_button.clicked.connect(self.partUp)
        self.down_button.clicked.connect(self.partDown)
        self.edit_button.clicked.connect(self.editPart)

        self.image_list = QListWidget()
        self.image_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        image_box = QVBoxLayout()
        image_box.addWidget(self.image_list)
        image_button_layout = QHBoxLayout()
        image_plus_button = FlatButton(":/images/plus.svg")
        self.image_trash_button = FlatButton(":/images/trash.svg")
        self.image_trash_button.enabled = False
        image_button_layout.addWidget(image_plus_button)
        image_button_layout.addWidget(self.image_trash_button)
        image_box.addLayout(image_button_layout)
        self.images.addLayout(image_box)
        image_plus_button.clicked.connect(self.addImage)
        self.image_trash_button.clicked.connect(self.dropImage)

        scroll_content = QWidget()
        scroll_content.setLayout(vbox)
        scroll = QScrollArea()
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setWidget(scroll_content)
        scroll.setWidgetResizable(True)
        scroll.setMaximumWidth(200)
        scroll.setMinimumWidth(200)

        self.navigationdock = QDockWidget("Navigation", self)
        self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea
                                            | Qt.RightDockWidgetArea)
        self.navigationdock.setWidget(scroll)
        self.navigationdock.setObjectName("Navigation")
        self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock)

        self.splitter = QSplitter()
        self.text_edit = MarkdownEdit()
        self.text_edit.setFont(QFont("Courier", 11))
        self.preview = QWebEngineView()
        self.preview.setMinimumWidth(300)
        self.setWindowTitle(QCoreApplication.applicationName())

        self.splitter.addWidget(self.text_edit)
        self.splitter.addWidget(self.preview)
        self.setCentralWidget(self.splitter)

        self.content.expanded.connect(self.contentExpanded)
        self.images.expanded.connect(self.imagesExpanded)
        self.settings.expanded.connect(self.settingsExpanded)
        self.settings.clicked.connect(self.openSettings)
        self.content_list.currentItemChanged.connect(self.partSelectionChanged)
        self.image_list.currentItemChanged.connect(self.imageSelectionChanged)
        self.image_list.itemDoubleClicked.connect(self.insertImage)

        self.text_edit.undoAvailable.connect(self.undoAvailable)
        self.text_edit.redoAvailable.connect(self.redoAvailable)
        self.text_edit.copyAvailable.connect(self.copyAvailable)

        QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged)

    def undoAvailable(self, value):
        self.undo_act.setEnabled(value)

    def redoAvailable(self, value):
        self.redo_act.setEnabled(value)

    def copyAvailable(self, value):
        self.copy_act.setEnabled(value)
        self.cut_act.setEnabled(value)

    def clipboardDataChanged(self):
        md = QApplication.clipboard().mimeData()
        self.paste_act.setEnabled(md.hasText())

    def openSettings(self):
        dlg = Settings(self.book)
        dlg.exec()
        if dlg.saved:
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

    def addPart(self):
        self.item_edit.setText("")
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = True

    def addItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.addPart(text)
                self.loadBook(self.last_book)

    def updateItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.updatePart(
                    self.content_list.currentItem().data(1).name, text)
                self.loadBook(self.last_book)

    def editItemFinished(self):
        if self._part_is_new:
            self.addItem()
        else:
            self.updateItem()
        self.item_anim.setStartValue(23)
        self.item_anim.setEndValue(0)
        self.item_anim.start()

    def editPart(self):
        item = self.content_list.currentItem().data(1).name
        self.item_edit.setText(item)
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = False

    def dropPart(self):
        item = self.content_list.currentItem().data(1).name
        msgBox = QMessageBox()
        msgBox.setText("You are about to delete the part <i>" + item + "</i>")
        msgBox.setInformativeText("Do you really want to delete the item?")
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        msgBox.setDefaultButton(QMessageBox.Cancel)
        ret = msgBox.exec()
        if ret == QMessageBox.Yes:
            self.book.dropPart(item)
            self.loadBook(self.last_book)

    def addImage(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("Image Files(*.png *.jpg *.bmp *.gif);;All (*)")
        dialog.setWindowTitle("Load Image")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return

        base = os.path.basename(fileName)
        if not os.path.exists(
                os.path.join(self.book.source_path, "images", base)):
            copy(fileName, os.path.join(self.book.source_path, "images"))
        item = QListWidgetItem()
        item.setText(Path(fileName).name)
        item.setData(
            1,
            os.path.join(self.book.source_path, "images",
                         Path(fileName).name))
        self.image_list.addItem(item)

    def dropImage(self):
        item = self.image_list.currentItem()
        image = item.data(1)
        filename = os.path.join(self.book.source_path, "parts", image)
        os.remove(filename)
        self.loadImages()

    def loadImages(self):
        self.image_list.clear()
        for root, dir, files in os.walk(
                os.path.join(self.book.source_path, "images")):
            for file in files:
                filename = os.path.join(self.book.source_path, "images",
                                        Path(file).name)
                item = QListWidgetItem()
                item.setToolTip("Doubleclick image to insert into text")
                item.setText(Path(file).name)
                item.setData(1, filename)
                self.image_list.addItem(item)

    def partUp(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos - 1, item)
        self.content_list.setCurrentRow(pos - 1)
        self.book.partUp(item.data(1).name)

    def partDown(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos + 1, item)
        self.content_list.setCurrentRow(pos + 1)
        self.book.partDown(item.data(1).name)

    def partSelectionChanged(self, item):
        if item:
            part = item.data(1)
            self.filename = os.path.join(self.book.source_path, "parts",
                                         part.src)
            with open(self.filename, "r") as f:
                self.text_edit.setText(f.read())
            self.trash_button.enabled = True
            self.up_button.enabled = self.content_list.currentRow() > 0
            self.down_button.enabled = self.content_list.currentRow(
            ) < self.content_list.count() - 1
            self.edit_button.enabled = True
        else:
            self.text_edit.setText("")
            self.trash_button.enabled = False
            self.up_button.enabled = False
            self.down_button.enabled = False
            self.edit_button.enabled = False

    def imageSelectionChanged(self, item):
        if item:
            self.image_trash_button.enabled = True
        else:
            self.image_trash_button.enabled = False

    def contentExpanded(self, value):
        if value:
            self.images.setExpanded(False)
            self.settings.setExpanded(False)

    def imagesExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.settings.setExpanded(False)

    def appearanceExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.images.setExpanded(False)
            self.settings.setExpanded(False)

    def settingsExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.images.setExpanded(False)

    def closeEvent(self, event):
        self.writeSettings()
        event.accept()

    def createMenus(self):
        new_icon = QIcon(QPixmap(":/images/new.svg"))
        open_icon = QIcon(QPixmap(":/images/open.svg"))
        book_icon = QIcon(QPixmap(":/images/book.svg"))
        bold_icon = QIcon(QPixmap(":/images/bold.svg"))
        italic_icon = QIcon(QPixmap(":/images/italic.svg"))
        image_icon = QIcon(QPixmap(":/images/image.svg"))
        table_icon = QIcon(QPixmap(":/images/table.svg"))

        new_act = QAction(new_icon, "&New", self)
        new_act.setShortcuts(QKeySequence.New)
        new_act.setStatusTip("Create a new ebook project")
        new_act.triggered.connect(self.newFile)
        new_act.setToolTip("Create new ebook project")

        open_act = QAction(open_icon, "&Open", self)
        open_act.setShortcuts(QKeySequence.Open)
        open_act.setStatusTip("Open an existing ebook project")
        open_act.triggered.connect(self.open)
        open_act.setToolTip("Open an existing ebook project")

        book_act = QAction(book_icon, "&Create Book", self)
        book_act.setShortcuts(QKeySequence.SaveAs)
        book_act.setStatusTip("Create an ebook")
        book_act.triggered.connect(self.create)
        book_act.setToolTip("Create an ebook")

        pdf_act = QAction("Create &PDF", self)
        pdf_act.setStatusTip("Create PDF")
        pdf_act.setToolTip("Create PDF")
        pdf_act.triggered.connect(self.pdfExport)

        settings_act = QAction("&Settings", self)
        settings_act.setStatusTip("Open settings dialog")
        settings_act.triggered.connect(self.settingsDialog)
        settings_act.setToolTip("Open settings dialog")

        exit_act = QAction("E&xit", self)
        exit_act.setShortcuts(QKeySequence.Quit)
        exit_act.setStatusTip("Exit the application")
        exit_act.triggered.connect(self.close)

        self.undo_act = QAction("Undo", self)
        self.undo_act.setShortcut(QKeySequence.Undo)
        self.undo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doUndo)

        self.redo_act = QAction("Redo", self)
        self.redo_act.setShortcut(QKeySequence.Redo)
        self.redo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doRedo)

        self.cut_act = QAction("Cu&t", self)
        self.cut_act.setShortcut(QKeySequence.Cut)
        self.cut_act.triggered.connect(self.doCut)
        self.cut_act.setEnabled(False)

        self.copy_act = QAction("&Copy", self)
        self.copy_act.setShortcut(QKeySequence.Copy)
        self.copy_act.triggered.connect(self.doCopy)
        self.copy_act.setEnabled(False)

        self.paste_act = QAction("&Paste", self)
        self.paste_act.setShortcut(QKeySequence.Paste)
        self.paste_act.triggered.connect(self.doPaste)
        self.paste_act.setEnabled(False)

        bold_act = QAction(bold_icon, "Bold", self)
        bold_act.setShortcut(Qt.CTRL + Qt.Key_B)
        bold_act.triggered.connect(self.bold)

        italic_act = QAction(italic_icon, "Italic", self)
        italic_act.setShortcut(Qt.CTRL + Qt.Key_I)
        italic_act.triggered.connect(self.italic)

        image_act = QAction(image_icon, "Image", self)
        image_act.setShortcut(Qt.CTRL + Qt.Key_G)
        image_act.triggered.connect(self.insertImage)
        image_act.setToolTip("Insert an image")

        table_act = QAction(table_icon, "Table", self)
        table_act.setShortcut(Qt.CTRL + Qt.Key_T)
        table_act.triggered.connect(self.insertTable)
        table_act.setToolTip("Insert a table")

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

        file_menu = self.menuBar().addMenu("&File")
        file_menu.addAction(new_act)
        file_menu.addAction(open_act)
        file_menu.addAction(book_act)
        file_menu.addAction(pdf_act)
        file_menu.addSeparator()
        file_menu.addAction(settings_act)
        file_menu.addSeparator()
        file_menu.addAction(exit_act)

        edit_menu = self.menuBar().addMenu("&Edit")
        edit_menu.addAction(self.undo_act)
        edit_menu.addAction(self.redo_act)
        edit_menu.addSeparator()
        edit_menu.addAction(self.cut_act)
        edit_menu.addAction(self.copy_act)
        edit_menu.addAction(self.paste_act)

        format_menu = self.menuBar().addMenu("&Format")
        format_menu.addAction(bold_act)
        format_menu.addAction(italic_act)

        insert_menu = self.menuBar().addMenu("&Insert")
        insert_menu.addAction(image_act)
        insert_menu.addAction(table_act)

        help_menu = self.menuBar().addMenu("&Help")
        help_menu.addAction(about_act)

        file_tool_bar = self.addToolBar("File")
        file_tool_bar.addAction(new_act)
        file_tool_bar.addAction(open_act)
        file_tool_bar.addAction(book_act)

        format_tool_bar = self.addToolBar("Format")
        format_tool_bar.addAction(bold_act)
        format_tool_bar.addAction(italic_act)

        insert_toolbar = self.addToolBar("Insert")
        insert_toolbar.addAction(image_act)
        insert_toolbar.addAction(table_act)

    def doUndo(self):
        self.text_edit.undo()

    def doRedo(self):
        self.text_edit.redo()

    def doCut(self):
        self.text_edit.cut()

    def doCopy(self):
        self.text_edit.copy()

    def doPaste(self):
        self.text_edit.paste()

    def insertImage(self):
        if not self.book:
            QMessageBox.warning(self, QCoreApplication.applicationName(),
                                "You have to load or create a book first!")
            return
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        if self.image_list.count() == 0:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to add an image to the image list first!")
            return
        if not self.image_list.currentItem():
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select an image from the image list first!")
            return

        item = self.image_list.currentItem()
        filename = item.text()
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        base = filename.split(".")[0].replace("_", "-")
        cursor.insertText("![" + base + "](../images/" + filename + " \"" +
                          base + "\")")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def insertTable(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText(
            "| alignLeft | alignCenter | unAligned | alignRight |\n"
            "|  :---     |   :---:     |   ---     |   ---:     |\n"
            "|  cell a   |   cell b    |   cell c  |   cell d   |\n"
            "|  cell e   |   cell f    |   cell g  |   cell h   |\n")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def about(self):
        QMessageBox.about(
            self, "About " + QCoreApplication.applicationName(),
            "EbookCreator\nVersion: " + QCoreApplication.applicationVersion() +
            "\n(C) Copyright 2019 Olaf Japp. All rights reserved.\n\nThis program is provided AS IS with NO\nWARRANTY OF ANY KIND, INCLUDING THE\nWARRANTY OF DESIGN, MERCHANTABILITY AND\nFITNESS FOR A PATICULAR PURPOSE."
        )

    def newFile(self):
        dlg = ProjectWizard(self.install_directory, parent=self)
        dlg.loadBook.connect(self.loadBook)
        dlg.show()

    def open(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("EbookCreator (book.qml);;All (*)")
        dialog.setWindowTitle("Load Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setDirectory(os.path.join(self.install_directory, "sources"))
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return
        self.loadBook(fileName)

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("lastBook", self.last_book)

    def readSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        geometry = settings.value("geometry", QByteArray())
        self.last_book = settings.value("lastBook")
        if not geometry:
            availableGeometry = QApplication.desktop().availableGeometry(self)
            self.resize(availableGeometry.width() / 3,
                        availableGeometry.height() / 2)
            self.move((availableGeometry.width() - self.width()) / 2,
                      (availableGeometry.height() - self.height()) / 2)
        else:
            self.restoreGeometry(geometry)

    def bold(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("**" + cursor.selectedText() + "**")
        cursor.setPosition(pos + 2)
        self.text_edit.setTextCursor(cursor)

    def italic(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("*" + cursor.selectedText() + "*")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def create(self):
        filename = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("ePub3 (*.epub);;All (*)")
        dialog.setWindowTitle("Create Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setDirectory(self.install_directory)
        dialog.setDefaultSuffix("epub")
        if dialog.exec_():
            filename = dialog.selectedFiles()[0]
        del dialog
        if not filename:
            return
        QApplication.setOverrideCursor(Qt.WaitCursor)
        createEpub(filename, self.book, self)
        QApplication.restoreOverrideCursor()

    def loadStatusChanged(self, status):
        if status == 1:
            self.book = self.component.create()
            if self.book is not None:
                self.book.setFilename(self.last_book)
                self.book.setWindow(self)
            else:
                for error in self.component.errors():
                    print(error.toString())
                return

            self.content_list.clear()
            for part in self.book.parts:
                item = QListWidgetItem()
                item.setText(part.name)
                item.setData(1, part)
                self.content_list.addItem(item)

            self.loadImages()
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

            self.content.setExpanded(True)
            self.content_list.setCurrentRow(0)
        elif status == 3:
            for error in self.component.errors():
                print(error.toString())
            return

    def loadBook(self, filename):
        self.last_book = filename
        self.filename = ""
        engine = QQmlEngine()
        self.component = QQmlComponent(engine)
        self.component.statusChanged.connect(self.loadStatusChanged)
        self.component.loadUrl(QUrl.fromLocalFile(filename))

    def settingsDialog(self):
        dlg = SettingsDialog(self.theme,
                             self.palette().highlight().color().name(),
                             parent=self)
        dlg.exec()
        if dlg.theme != self.theme or dlg.hilite_color != self.palette(
        ).highlight().color().name():
            settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                                 QCoreApplication.organizationName(),
                                 QCoreApplication.applicationName())
            settings.setValue("theme", dlg.theme)
            settings.setValue("hiliteColor", dlg.hilite_color)

            msgBox = QMessageBox()
            msgBox.setText("Please restart the app to change the theme!")
            msgBox.exec()

    def textChanged(self):
        if self.filename:
            with open(self.filename, "w") as f:
                f.write(self.text_edit.toPlainText())

        self.lock = Lock()
        with self.lock:
            if not self.tread_running:
                self.tread_running = True
                self.htmlReady.connect(self.previewReady)
                thread = Thread(target=self.createHtml,
                                args=(self.text_edit.toPlainText(), ))
                thread.daemon = True
                thread.start()

    def previewReady(self, html):
        self.preview.setHtml(
            html,
            baseUrl=QUrl(
                Path(os.path.join(self.book.source_path, "parts",
                                  "index.html")).as_uri()))
        self.htmlReady.disconnect()
        with self.lock:
            self.tread_running = False

    def createHtml(self, text):
        html = "<html>\n<head>\n"
        html += "<link href=\"../css/pastie.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
        html += "<link href=\"../css/stylesheet.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
        html += "</head>\n<body>\n"
        html += markdown(text,
                         html4tags=False,
                         extras=[
                             "fenced-code-blocks", "wiki-tables", "tables",
                             "header-ids"
                         ])
        html += "\n</body>\n</html>"
        html = addLineNumbers(html)
        self.htmlReady.emit(html)

    def pdfExport(self):
        p = PdfExport("test.pdf", self.book, self.statusBar())
Пример #16
0
class MainProcess(MainProcessUI):
    def __init__(self):
        super(MainProcess, self).__init__()

        # use for convert
        self.__elev_ptn = re.compile(r"(.*),(.*)")
        self.__file_ptn = re.compile(r"FG-GML-(.*)-(.*)-(.*)-.*(A|B|C)-.*.xml")
        self.__sp_ptn = re.compile(
            r"<gml:startPoint>(.*) (.*)</gml:startPoint>")
        self.__lc_ptn = re.compile(
            r"<gml:lowerCorner>.* (.*)</gml:lowerCorner>")
        self.__uc_ptn = re.compile(
            r"<gml:upperCorner>(.*) .*</gml:upperCorner>")
        self.__load_cnt = 0
        self.__cnt = 0
        self.__sp = 0

        self.__missing = False

        self.__lat_for_file0 = set()
        self.__lon_for_file0 = set()

        # lat
        self.__lat_index = 0
        self.__lat_diff = 0.008333333

        # lon
        self.__lon_index = 0

        # Later: I will support 10m DEM and more
        self.__width = 225
        self.__height = 150
        self.__size = self.__width * self.__height

        self.__db_dir, self.__xml_dir = Ds().getDir()

        #self.lc_lats, self.lc_lons, self.uc_lats, self.uc_lons = [], [], [], []
        #self.__getLcNumArray()

        self.__que = deque()

        # DnD
        self.setAcceptDrops(True)

        # path list
        self.__xmlPathList = []
        self.FileList = QListWidget()

        self.initUI()

    def onClicked(self):
        if len(self.__xmlPathList) == 0:
            return
        # start sub_process
        self.notifier = Notifier()
        self.thread = Thread(self.notifier, "convert")
        self.notifier.moveToThread(self.thread)
        self.notifier.notify.connect(self.__clickedStart,
                                     type=Qt.DirectConnection)
        self.thread.start()
        self.thread.finished.connect(self.__finishSubProcess)

    def __clickedStart(self):
        table_tmp = 0
        cnt = 0
        check_file_tmp = -1
        xmlPathList = self.__xmlPathList[:]
        for index, xml_path in enumerate(xmlPathList):
            match_file = Search(self.__file_ptn, basename(xml_path))

            # When the same file of DEM5A and DEM5B exists in the list
            check_for_DEM_x = Group(match_file, 1) + '-' + Group(
                match_file, 2) + '-' + Group(match_file, 3)
            if index + 1 != len(
                    xmlPathList) and check_for_DEM_x in xmlPathList[index + 1]:
                if self.__checkNextFileDEMType(xmlPathList[index + 1]):
                    continue

            table = Group(match_file, 1) + Group(match_file, 2)
            if table != table_tmp:
                if self.__lat_for_file0 and self.__lon_for_file0:
                    self.__MinLatLonIntoDB(min(self.__lat_for_file0),
                                           min(self.__lon_for_file0))
                table_tmp = table
                self.__convertReset()
                check_file_tmp = -1
                cnt = 0

            check_file = int(Group(match_file, 3))
            check_file_diff = check_file - check_file_tmp
            if check_file_diff > 1:
                self.__missing = True
            check_file_tmp = check_file

            conn = sqlite3.connect(self.__db_dir + "testterrain6.db")
            cur = conn.cursor()
            sql = cur.execute
            self.__table_name = "fg" + table
            sql("""
        CREATE TABLE IF NOT EXISTS {} 
        (elevation double(5, 2), 
         lat_index int,
         lon_index int,
        lc_lat_num int, 
        lc_lon_num int, 
        uc_lat_num int, 
        uc_lon_num int);""".format(self.__table_name))

            query = """INSERT INTO {} 
              (elevation, lat_index, lon_index, lc_lat_num, lc_lon_num, uc_lat_num, uc_lon_num) 
              VALUES (?, ?, ?, ?, ?, ?, ?);""".format(self.__table_name)
            cnt += check_file_diff
            if self.__missing:
                for _ in range(check_file_diff - 1):
                    elevation, lats, lons, lc_lats, lc_lons, uc_lats, uc_lons = self.__GetMissing(
                    )
                    dataset = [
                        x for x in zip(elevation, lats, lons, lc_lats, lc_lons,
                                       uc_lats, uc_lons)
                    ]
                    cur.executemany(query, dataset)
                    conn.commit()
                self.__missing = False
            self.__getStartPoint(xml_path)
            elevation, lats, lons, lc_lats, lc_lons, uc_lats, uc_lons = self.__convert(
                xml_path)

            dataset = [
                x for x in zip(elevation, lats, lons, lc_lats, lc_lons,
                               uc_lats, uc_lons)
            ]
            cur.executemany(query, dataset)
            conn.commit()

            if xml_path == xmlPathList[-1]:
                self.__MinLatLonIntoDB(min(self.__lat_for_file0),
                                       min(self.__lon_for_file0))

                match = Search(self.__file_ptn, xml_path)
                file_name = int(Group(match, 3))
                if file_name != 99:
                    for _ in range(99 - file_name):
                        elevation, lats, lons, lc_lats, lc_lons, uc_lats, uc_lons = self.__GetMissing(
                        )
                        dataset = [
                            x for x in zip(elevation, lats, lons, lc_lats,
                                           lc_lons, uc_lats, uc_lons)
                        ]
                        cur.executemany(query, dataset)
                        conn.commit()
        cur.close()
        conn.close()
        print(cnt)

    def __finishSubProcess(self):
        #QMessageBox.information(self, "Message", "Finished convert", QMessageBox.Ok)
        print("fin")

    def __checkNextFileDEMType(self, next_file):
        match_file = self.__file_ptn.search(os.path.basename(next_file))
        DEM_type = match_file.group(4)
        if DEM_type in ('A', 'B', 'C'):
            return True
        return False

    def __GetMissing(self):
        elev = [SEALEVEL - 1000] * self.__size
        self.__convertLoad()
        lc_lats, lc_lons, uc_lats, uc_lons = self.__getLcUcNumArray()
        lats = [self.__lat_index] * self.__size
        lons = [self.__lon_index] * self.__size
        self.__lon_index += 1
        return (elev, lats, lons, lc_lats, lc_lons, uc_lats, uc_lons)

    def __convertReset(self):
        self.__load_cnt = 0
        self.__cnt = 0
        self.__lat_index = 0
        self.__lon_index = 0
        self.__lat_for_file0 = set()
        self.__lon_for_file0 = set()

    def __convert(self, filename):
        with open(filename, "r", encoding="utf-8_sig") as f:
            elevations = []
            for line in f.readlines():
                lc_match = self.__lc_ptn.search(line)
                if lc_match:
                    lc_lon = float(lc_match.group(1))
                    self.__lon_for_file0.add(lc_lon)
                    lc_match = 0

                uc_match = self.__uc_ptn.search(line)
                if uc_match:
                    uc_lat = float(uc_match.group(1))
                    lc_lat = uc_lat - self.__lat_diff
                    self.__lat_for_file0.add(lc_lat)
                    self.__MinLatLonIntoDB(lc_lat, lc_lon)
                    uc_match = 0
                    self.__convertLoad()

                el_match = self.__elev_ptn.search(line)
                if el_match:
                    typ, data = line.split(",")
                    data = float(data)
                    if typ in (u"データなし", u"海水面", u"内水面"):
                        data = -1000.0
                    elevations.append(data)

        lc_lats, lc_lons, uc_lats, uc_lons = self.__getLcUcNumArray()
        new_elevations = self.__adjustArray(elevations)
        lats = [self.__lat_index] * self.__size
        lons = [self.__lon_index] * self.__size
        #print(self.lat_index, self.lon_index, self.load_cnt)
        self.__lon_index += 1
        f.close()
        return (new_elevations, lats, lons, lc_lats, lc_lons, uc_lats, uc_lons)

    def __convertLoad(self):
        if self.__load_cnt >= 10:
            self.__cnt += 1
            self.__lat_index += 1
            self.__load_cnt = 0
            self.__lon_index = 0
        self.__load_cnt += 1

    def __getLcUcNumArray(self):
        lc_lats, lc_lons, uc_lats, uc_lons = [], [], [], []
        lat_num = self.__height + self.__height * self.__cnt
        lon_num = (self.__load_cnt - 1) * self.__width
        #print(lat_num, lon_num)
        cnt = 0
        while cnt != self.__size:
            if lon_num > self.__load_cnt * self.__width - 1:
                lon_num = (self.__load_cnt - 1) * self.__width
                lat_num -= 1
            lc_lats.append(lat_num - 1)
            lc_lons.append(lon_num)
            uc_lats.append(lat_num)
            uc_lons.append(lon_num + 1)
            lon_num += 1
            cnt += 1
        return (lc_lats, lc_lons, uc_lats, uc_lons)

    def __getStartPoint(self, filename):
        with open(filename, "r", encoding="utf-8_sig") as f:
            while True:
                line = f.readline()
                sp_match = self.__sp_ptn.search(line)
                if sp_match:
                    sp_lon, sp_lat = int(sp_match.group(1)), int(
                        sp_match.group(2))
                    self.__sp = sp_lat * self.__width + sp_lon
                    return

    def __adjustArray(self, array):
        return [-1000.0] * self.__sp + array + (self.__size - self.__sp -
                                                len(array)) * [-1000.0]

    def __MinLatLonIntoDB(self, lc_lat, lc_lon):
        conn = sqlite3.connect(self.__db_dir + "latlon.db")
        cur = conn.cursor()
        sql = cur.execute
        if self.__inTable(conn, cur):
            cur.close()
            conn.close()
            return
        sql("CREATE TABLE IF NOT EXISTS {}(lat double(3, 9), lon double(3, 9))"
            .format(self.__table_name))
        sql("INSERT INTO {} (lat, lon) VALUES('{}', '{}')".format(
            self.__table_name, lc_lat, lc_lon))
        conn.commit()
        cur.close()
        conn.close()

    def __inTable(self, conn, cur):
        cur.execute("select * from sqlite_master where type = 'table';")
        while True:
            v = cur.fetchone()
            if v == None:
                break
            if self.__table_name in v:
                return True
        return False

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        urls = event.mimeData().urls()
        for url in urls:
            path = adjustSep(url.toLocalFile())
            tmp = path.split('.')
            if path in self.__xmlPathList:
                QMessageBox.information(self, 'Warning',
                                        'This file already in.',
                                        QMessageBox.Ok)
                continue
            if len(tmp) != 1:
                if inExtension(path):
                    self.FileList.addItem(basename(path))
                    self.__xmlPathList.append(path)
            else:
                self.__addDir(tmp[0])

    def __addDir(self, item):
        for roots, dirs, files in os.walk(item):
            for f in files:
                if inExtension(f):
                    self.FileList.addItem(basename(f))
                    self.__xmlPathList.append(adjustSep(roots + '/' + f))

            if len(dirs) != 0:
                for d in dirs:
                    self.__que.append(d)
                return self.__addDir(self.__que.popleft())

        try:
            if len(self.__que) != 0:
                return self.__addDir(self.__que.popleft())
        except:
            return

    def clickedClear(self):
        self.FileList.clear()
        self.__xmlPathList = []

    def clickedExit(self):
        exit()

    def clickedAdd(self):
        filename, ok = QFileDialog.getOpenFileNames(self,
                                                    "Open File",
                                                    self.__xml_dir,
                                                    filter="xml file (*.xml)")
        # if clicked cancel
        if not ok:
            return
        for f in filename:
            f = adjustSep(f)
            if f in self.__xmlPathList:
                continue
            self.FileList.addItem(basename(f))
            self.__xmlPathList.append(self.replaceSep(f))

    def clickedSort(self):
        self.__xmlPathList.sort(key=lambda x: basename(x))
        self.FileList.sortItems()

    def clickedDelete(self):
        try:
            row = self.FileList.row(self.FileList.selectedItems()[0])
            self.__xmlPathList.pop(row)
            self.FileList.takeItem(row)
        except:
            pass
Пример #17
0
class class_search(QLineEdit):
    get_api_doc_signal = pyqtSignal(str)

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

        #             设置下拉列表的属性
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        p = self.geometry()
        self.lv_class = QListWidget()
        self.lv_class.setParent(self)
        self.lv_class.setAttribute(Qt.WA_ShowWithoutActivating)
        self.lv_class.setSizePolicy(sizePolicy)
        self.lv_class.setFixedSize(QSize(500, 500))
        self.lv_class.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint
                                     | Qt.WindowStaysOnTopHint)

        self.textChanged.connect(self.on_le_class_currentTextChanged)

        self.adding_lv_class_flag = False

    def on_le_class_currentTextChanged(self):
        cur_class = self.text()
        if len(cur_class) < 3:
            return

#             self.lv_class.setFixedSize(QSize(500,500))
        p = self.geometry()
        self.lv_class.move(QPoint(p.x(), p.y() + 50))

        result_list = []
        for c in self.class_list:
            if cur_class.lower() in c["name"].lower():
                result_list.append(c)
        self.popup_class_search_result(result_list)

#         弹出类的索引列表

    def popup_class_search_result(self, result_list):
        path_list = [item["path"] for item in result_list]
        if path_list:
            self.lv_class.setVisible(True)
            self.adding_lv_class_flag = True
            self.lv_class.clear()

            #             弹窗默认选中空白项,避免on_lv_class_currentItemChanged总是莫名选中选中第一项的bug
            blank_item = QListWidgetItem("")
            self.lv_class.addItem(blank_item)
            self.lv_class.setCurrentItem(blank_item)

            self.lv_class.addItems(path_list)
            self.adding_lv_class_flag = False

#         查询选中的类的文档

    def get_doc(self):
        if not self.adding_lv_class_flag:
            cur_item = self.lv_class.currentItem()
            #                 print("previous",previous.text())
            #                 if not cur_item :
            #                     print("currentText",self.lv_class.currentText())
            if cur_item and cur_item.text() != "":
                print("cur_item.text():" + cur_item.text())
                self.get_api_doc_signal.emit(cur_item.text())
#                 self.lv_class.setFixedSize(QSize(500,0))
            self.lv_class.setVisible(False)

    def keyReleaseEvent(self, event):
        key = event.key()
        if key == Qt.Key_Down:
            self.lv_class.setCurrentRow(self.lv_class.currentRow() + 1)
        elif key == Qt.Key_Up:
            self.lv_class.setCurrentRow(self.lv_class.currentRow() - 1)
        elif key == Qt.Key_Home:
            self.lv_class.setCurrentRow(1)
        elif key == Qt.Key_End:
            self.lv_class.setCurrentRow(self.lv_class.count() - 1)
        elif key == Qt.Key_PageUp:
            row = self.lv_class.currentRow() - 5
            if row > -1:
                self.lv_class.setCurrentRow(row)
        elif key == Qt.Key_PageDown:
            row = self.lv_class.currentRow() + 5
            if row < self.lv_class.count():
                self.lv_class.setCurrentRow(row)
        elif key == Qt.Key_Right or key == Qt.Key_Return:
            self.get_doc()
        elif key == Qt.Key_Escape:
            self.lv_class.setVisible(False)
Пример #18
0
class DriverWindow(QWidget):
    def __init__(self):
        super().__init__()

        # layouts

        groupbox_hdd_info = QGroupBox('HDD info')
        groupbox_system_info = QGroupBox('System info')
        groupbox_send_data_info = QGroupBox('Send')
        groupbox_app_info = QGroupBox('App info')

        grid_hdd_info = QGridLayout()
        grid_system_info = QGridLayout()
        grid_send_data_info = QGridLayout()
        grid_app_info = QGridLayout()

        groupbox_hdd_info.setLayout(grid_hdd_info)
        groupbox_system_info.setLayout(grid_system_info)
        groupbox_send_data_info.setLayout(grid_send_data_info)
        groupbox_app_info.setLayout(grid_app_info)

        grid_layout = QGridLayout()

        grid_layout.addWidget(groupbox_hdd_info)
        grid_layout.addWidget(groupbox_system_info)
        grid_layout.addWidget(groupbox_send_data_info)
        grid_layout.addWidget(groupbox_app_info)

        # driver name
        self.driver_name_label = QLabel('Driver name')
        self.driver_name_text = QLineEdit()
        self.driver_name_text.setPlaceholderText('enter your name')

        # car name
        self.car_name_label = QLabel('Car name')
        self.car_name_text = QLineEdit()
        self.car_name_text.setText(my_hdd.car_name)
        self.car_name_text.setReadOnly(True)

        # HDD id
        self.hdd_id_label = QLabel('HDD Serial Number')
        self.hdd_id_text = QLineEdit()
        self.hdd_id_text.setText(my_hdd.hdd_serial_number)
        self.hdd_id_text.setReadOnly(True)

        # number of sessions
        self.count_sessions_label = QLabel('Number of sessions')
        self.count_sessions_text = QLineEdit()
        self.count_sessions_text.setText(str(my_hdd.number_of_session))
        self.count_sessions_text.setReadOnly(True)

        # sessions range
        # start_date
        self.start_date_label = QLabel('First & Last Session')
        self.start_date_text = QLineEdit()
        self.start_date_text.setText(my_hdd.start_date)
        self.start_date_text.setReadOnly(True)

        ##end date
        self.end_date_label = QLabel('Last Session')
        self.end_date_text = QLineEdit()
        self.end_date_text.setText(my_hdd.end_date)
        self.end_date_text.setReadOnly(True)

        # list of sessions
        self.sessions_list_label = QLabel('sessions')
        self.sessions_list_text = QListWidget()
        self.sessions_list_text.addItems([x for x in my_hdd.session_list])
        # sessions_list_text.setReadOnly(True)

        # AWB number
        self.airwaybill_label = QLabel('AWB name')
        self.airwaybill_text = QLineEdit()
        self.airwaybill_text.setPlaceholderText(
            'enter AWB number if you have it')

        # code
        self.generated_code_label = QLabel('Generated code')
        self.generated_code_text = QLineEdit()
        self.generated_code = code_generator(
            my_hdd.car_name, current_date_for_gc.replace('_', '-'), 3)
        self.generated_code_text.setText(self.generated_code)
        self.generated_code_text.setReadOnly(True)

        # vpn
        self.vpn_label = QLabel('VPN')
        self.vpn_connection_label = QLabel('checking...')

        # hdd status health

        self.hdd_health_status_label = QLabel('HDD Health status')
        self.check_hdd_health_status_label = QLabel('Add hdd to check')

        self.notes = QPlainTextEdit()
        self.notes.setPlaceholderText("driver's notes")

        # hdds

        # 1
        self.hdd_1_label = QLabel()
        self.hdd_1_hddid_label = QLabel()
        self.hdd_1_start_date_label = QLabel()
        self.hdd_1_end_date_label = QLabel()
        self.hdd_1_num_sessions_label = QLabel()
        self.hdd_1_icon_label = QLabel()

        # 2
        self.hdd_2_label = QLabel()
        self.hdd_2_hddid_label = QLabel()
        self.hdd_2_start_date_label = QLabel()
        self.hdd_2_end_date_label = QLabel()
        self.hdd_2_num_sessions_label = QLabel()
        self.hdd_2_icon_label = QLabel()

        # 3
        self.hdd_3_label = QLabel()
        self.hdd_3_hddid_label = QLabel()
        self.hdd_3_start_date_label = QLabel()
        self.hdd_3_end_date_label = QLabel()
        self.hdd_3_num_sessions_label = QLabel()
        self.hdd_3_icon_label = QLabel()

        # 4
        self.hdd_4_number = QLabel()
        self.hdd_4_label = QLabel()
        self.hdd_4_hddid_label = QLabel()
        self.hdd_4_start_date_label = QLabel()
        self.hdd_4_end_date_label = QLabel()
        self.hdd_4_num_sessions_label = QLabel()
        self.hdd_4_icon_label = QLabel()

        # 5
        self.hdd_5_number = QLabel()
        self.hdd_5_label = QLabel()
        self.hdd_5_hddid_label = QLabel()
        self.hdd_5_start_date_label = QLabel()
        self.hdd_5_end_date_label = QLabel()
        self.hdd_5_num_sessions_label = QLabel()
        self.hdd_5_icon_label = QLabel()

        # version
        self.version = QLabel('Version')
        self.version_label = QLabel(version)

        # add_button
        add_button = QPushButton('Add new HDD to the shipment', self)
        add_button.setIcon(QtGui.QIcon('images/HDD-512.png'))
        add_button.setIconSize(QtCore.QSize(50, 50))
        add_button.clicked.connect(self.add_new_hdd)
        add_button.setToolTip('Add ndew Hdd to the queue')
        add_button.setStyleSheet('color:blue')
        add_button.setStyleSheet("background-color:#B7D9FF")

        # button
        button = QPushButton('Send HDD information', self)
        button.setIcon(QtGui.QIcon('images/send.png'))
        button.setIconSize(QtCore.QSize(65, 65))
        button.clicked.connect(self.show_popup)
        button.setToolTip('Send information to database')
        button.setStyleSheet('color:green')
        button.setStyleSheet("background-color:#CCFFCC;")

        self.message_window = QMessageBox()
        self.message_window.setWindowTitle('Info')

        self.txt_review = QLineEdit()
        self.txt_review.setPlaceholderText('enter your opinion')

        # # GRID
        #
        # grid_layout = QGridLayout()
        # grid_layout.setSpacing(3)
        #
        # # Drivers name
        grid_hdd_info.addWidget(self.driver_name_label, 1,
                                0)  # column 1, row 0
        grid_hdd_info.addWidget(self.driver_name_text, 1, 1)
        #
        # # Car name
        grid_hdd_info.addWidget(self.car_name_label, 2, 0)  # column 1, row 0
        grid_hdd_info.addWidget(self.car_name_text, 2, 1)
        #
        # # HDD ID
        grid_hdd_info.addWidget(self.hdd_id_label, 3, 0)
        grid_hdd_info.addWidget(self.hdd_id_text, 3,
                                1)  # column 2, row 1 to column 5 row 1
        #
        # # number of sessions
        grid_hdd_info.addWidget(self.count_sessions_label, 4, 0)
        grid_hdd_info.addWidget(self.count_sessions_text, 4,
                                1)  # column 2, row 1 to column 5 row 1
        #
        # # sessions range
        grid_hdd_info.addWidget(self.start_date_label, 5, 0)
        grid_hdd_info.addWidget(self.start_date_text, 5, 1)
        grid_hdd_info.addWidget(self.end_date_label, 6, 0)
        grid_hdd_info.addWidget(self.end_date_text, 6, 1)
        #
        # # awb number
        grid_hdd_info.addWidget(self.airwaybill_label, 7, 0)
        grid_hdd_info.addWidget(self.airwaybill_text, 7, 1)

        # generated code
        grid_hdd_info.addWidget(self.generated_code_label, 8, 0)
        grid_hdd_info.addWidget(self.generated_code_text, 8, 1)
        #
        # list of sessions
        grid_hdd_info.addWidget(self.sessions_list_text, 1, 3, 8, 3)

        # hdd health status
        grid_hdd_info.addWidget(self.hdd_health_status_label, 9, 0)
        grid_hdd_info.addWidget(self.check_hdd_health_status_label, 9, 1)

        # vpn
        grid_system_info.addWidget(self.vpn_label, 0, 0)
        grid_system_info.addWidget(self.vpn_connection_label, 0, 1, 1, 3)

        # notes
        grid_system_info.addWidget(self.notes, 1, 0, 1, 4)

        #
        # # hdds
        grid_send_data_info.addWidget(self.hdd_1_label, 1, 0)
        grid_send_data_info.addWidget(self.hdd_1_hddid_label, 1, 2)
        grid_send_data_info.addWidget(self.hdd_1_start_date_label, 1, 4)
        grid_send_data_info.addWidget(self.hdd_1_end_date_label, 1, 5)
        grid_send_data_info.addWidget(self.hdd_1_num_sessions_label, 1, 8)
        grid_send_data_info.addWidget(self.hdd_1_icon_label, 1, 9)
        grid_send_data_info.addWidget(self.hdd_2_label, 2, 0)
        grid_send_data_info.addWidget(self.hdd_2_hddid_label, 2, 2)
        grid_send_data_info.addWidget(self.hdd_2_start_date_label, 2, 4)
        grid_send_data_info.addWidget(self.hdd_2_end_date_label, 2, 5)
        grid_send_data_info.addWidget(self.hdd_2_num_sessions_label, 2, 8)
        grid_send_data_info.addWidget(self.hdd_2_icon_label, 2, 9)
        grid_send_data_info.addWidget(self.hdd_3_label, 3, 0)
        grid_send_data_info.addWidget(self.hdd_3_hddid_label, 3, 2)
        grid_send_data_info.addWidget(self.hdd_3_start_date_label, 3, 4)
        grid_send_data_info.addWidget(self.hdd_3_end_date_label, 3, 5)
        grid_send_data_info.addWidget(self.hdd_3_num_sessions_label, 3, 8)
        grid_send_data_info.addWidget(self.hdd_3_icon_label, 3, 9)
        grid_send_data_info.addWidget(self.hdd_4_label, 4, 0)
        grid_send_data_info.addWidget(self.hdd_4_hddid_label, 4, 2)
        grid_send_data_info.addWidget(self.hdd_4_start_date_label, 4, 4)
        grid_send_data_info.addWidget(self.hdd_4_end_date_label, 4, 5)
        grid_send_data_info.addWidget(self.hdd_4_num_sessions_label, 4, 8)
        grid_send_data_info.addWidget(self.hdd_4_icon_label, 4, 9)
        grid_send_data_info.addWidget(self.hdd_5_label, 5, 0)
        grid_send_data_info.addWidget(self.hdd_5_hddid_label, 5, 2)
        grid_send_data_info.addWidget(self.hdd_5_start_date_label, 5, 4)
        grid_send_data_info.addWidget(self.hdd_5_end_date_label, 5, 5)
        grid_send_data_info.addWidget(self.hdd_5_num_sessions_label, 5, 8)
        grid_send_data_info.addWidget(self.hdd_5_icon_label, 5, 9)
        #
        # # version
        #
        grid_app_info.addWidget(self.version, 0, 0)
        grid_app_info.addWidget(self.version_label, 0, 1, 1, 3)
        #
        # # button
        grid_send_data_info.addWidget(add_button, 0, 0, 1, 10)
        grid_send_data_info.addWidget(button, 8, 0, 1, 10)

        # creating hdd's labels
        self.hdd_labels = [
            [
                self.hdd_1_label, self.hdd_1_hddid_label,
                self.hdd_1_start_date_label, self.hdd_1_end_date_label,
                self.hdd_1_num_sessions_label, self.hdd_1_icon_label
            ],
            [
                self.hdd_2_label, self.hdd_2_hddid_label,
                self.hdd_2_start_date_label, self.hdd_2_end_date_label,
                self.hdd_2_num_sessions_label, self.hdd_2_icon_label
            ],
            [
                self.hdd_3_label, self.hdd_3_hddid_label,
                self.hdd_3_start_date_label, self.hdd_3_end_date_label,
                self.hdd_3_num_sessions_label, self.hdd_3_icon_label
            ],
            [
                self.hdd_4_label, self.hdd_4_hddid_label,
                self.hdd_4_start_date_label, self.hdd_4_end_date_label,
                self.hdd_4_num_sessions_label, self.hdd_4_icon_label
            ],
            [
                self.hdd_5_label, self.hdd_5_hddid_label,
                self.hdd_5_start_date_label, self.hdd_5_end_date_label,
                self.hdd_5_num_sessions_label, self.hdd_5_icon_label
            ]
        ]

        # Qtimer
        timer = QTimer(self)
        timer.timeout.connect(self.refresh_hdd)
        timer.start(1200)

        timer2 = QTimer(self)
        timer2.timeout.connect(self.check_vpn_connection)
        timer2.start(10000)

        self.setLayout(grid_layout)
        self.setGeometry(
            500,  # x
            400,  # y
            600,
            640)
        self.setWindowTitle('HDD tracker')
        self.setWindowIcon(QtGui.QIcon('send.png'))

    hdds = []

    def check_vpn_connection(self):
        check_vpn(self.vpn_connection_label)

    def refresh_hdd(self):
        find_disks()
        new_hdd = create_hdd_object()
        if len(new_hdd.session_list) == 0:
            self.sessions_list_text.clear()
            self.car_name_text.setStyleSheet('color:red')
            self.start_date_text.setStyleSheet('color:red')
            self.end_date_text.setStyleSheet('color:red')
            self.hdd_id_text.setStyleSheet('color:red')
            self.count_sessions_text.setStyleSheet('color:red')
            self.count_sessions_text.setText(str(new_hdd.number_of_session))
            self.car_name_text.setText(str(new_hdd.car_name))
            self.hdd_id_text.setText('')
            self.start_date_text.setText(str(new_hdd.start_date))
            self.end_date_text.setText(str(new_hdd.end_date))
            self.sessions_list_text.clear()
            self.sessions_list_text.addItems([x for x in new_hdd.session_list])
            self.generated_code_text.setText(self.generated_code)
        else:
            try:
                obj = parase_crystaldisk()
            except FileNotFoundError:
                logging.info(f'{current_date}No DiskInfo.txt of file is empty')
            self.car_name_text.setStyleSheet('color:darkgreen')
            self.start_date_text.setStyleSheet('color:darkgreen')
            self.end_date_text.setStyleSheet('color:darkgreen')
            self.generated_code_text.setStyleSheet('color:darkgreen')
            self.hdd_id_text.setStyleSheet('color:darkgreen')
            self.count_sessions_text.setStyleSheet('color:darkgreen')
            self.generated_code_text.setStyleSheet('color:blue')
            self.count_sessions_text.setText(str(new_hdd.number_of_session))
            self.car_name_text.setText(str(new_hdd.car_name))
            self.hdd_id_text.setText(
                str(obj['disks'][len(obj['disks']) - 1]
                    ['Serial Number']))  # added last element from disk's list
            self.start_date_text.setText(str(new_hdd.start_date))
            self.end_date_text.setText(str(new_hdd.end_date))
            self.sessions_list_text.clear()
            self.sessions_list_text.addItems([x for x in new_hdd.session_list])
            if self.generated_code == 'no hdd':
                self.generated_code = code_generator(
                    new_hdd.car_name, current_date_for_gc.replace('_', '-'), 3)
                self.generated_code_text.setText(self.generated_code)
                print(self.generated_code)

    print(current_date)
    number_of_hdd = 0

    # creating new shipment template
    new_shipment = {
        'id': None,
        'status': 'prepared',
        'create_date': current_date,
        "DHL_data": {
            "awb": "-",
            "event_date": "-",
            "event_desc": "-",
            "event_signatory": "-",
            "event_time": "-",
            "ref_id": "-",
            "ship_date": "-",
            "ship_to": "-",
            "shipper_name": "-",
            "status_code": "-"
        },
        "self_delivery_data": {
            "location": "-",
            "comment": "-"
        },
        'driver': '-',
        'disks': [],
        "previous_status": "-",
        "status_history": {
            "prepared": current_date,
            "sent": "-",
            "self_delivered": "-",
            "delivered": "-",
            "received": "-"
        },
        "_rid": "FNx-AOmVdYQjAAAAAAAAAA==",
        "_self":
        "dbs/FNx-AA==/colls/FNx-AOmVdYQ=/docs/FNx-AOmVdYQjAAAAAAAAAA==/",
        "_etag": "\"85005be0-0000-0d00-0000-5fa95b4a0000\"",
        "_attachments": "attachments/",
        "_ts": 1604934474
    }

    @pyqtSlot()
    def add_new_hdd(self):
        filePath = f'{__location__}\DiskInfo.txt'
        modificationTime = get_last_file_modified_data(filePath)

        # executing CrystalDiskInfo

        logging.info(f'\n{current_date}\nExecuting Cristal Disk info')
        subprocess.run([
            "powershell", "start", f"'{__location__}\DiskInfo64.exe'",
            "-ArgumentList", "/CopyExit ", "-Verb", "Runas"
        ])
        logging.info(f'\n{current_date}\nExecuting Cristal Disk Info done')
        modificationTimeNew = get_last_file_modified_data(filePath)

        # comparing last modification date to make sure that file is already updated
        while modificationTime == modificationTimeNew:
            modificationTimeNew = get_last_file_modified_data(filePath)
            print(Fore.YELLOW + "Waiting for DiskInfo.txt update")
            time.sleep(0.5)
        print('')
        print(Fore.GREEN + 'Success')
        time.sleep(0.5)
        print(Fore.GREEN + "DiskInfo.txt has been updated")
        obj = parase_crystaldisk()
        logging.info(
            f'\n{current_date}\nDiskInfo.txt has been updated\nObject: {obj}')
        new_hdd = create_hdd_object()
        self.new_shipment['id'] = self.generated_code
        self.new_shipment['driver'] = self.driver_name_text.text()

        new_disk = {
            'carname':
            new_hdd.car_name,
            'hdd_serial_number':
            obj['disks'][len(obj['disks']) - 1]['Serial Number'],
            'health_status':
            '-',
            'sessions_from':
            new_hdd.start_date,
            'sessions_to':
            new_hdd.end_date,
            'sessions':
            new_hdd.session_list
        }
        try:
            new_disk['health_status'] = obj['disks'][len(obj['disks']) -
                                                     1]['Health Status']
            heatlh_status(self.check_hdd_health_status_label,
                          obj['disks'][len(obj['disks']) - 1]['Health Status'])
        except:
            pass

        if new_disk not in self.new_shipment[
                'disks'] and new_disk['carname'] != 'no hdd':
            print(Fore.GREEN + 'HDD has been just added to the shipment\n')
            self.new_shipment['disks'].append(new_disk)

            self.hdd_labels[self.number_of_hdd][0].setText(new_hdd.car_name)
            self.hdd_labels[self.number_of_hdd][0].setStyleSheet(
                'background-color: #00ff00')
            self.hdd_labels[self.number_of_hdd][1].setText(
                new_disk['hdd_serial_number'])
            self.hdd_labels[self.number_of_hdd][1].setStyleSheet(
                'background-color: #00ff00')
            self.hdd_labels[self.number_of_hdd][2].setText(new_hdd.start_date)
            self.hdd_labels[self.number_of_hdd][2].setStyleSheet(
                'background-color: #00ff00')
            self.hdd_labels[self.number_of_hdd][3].setText(new_hdd.end_date)
            self.hdd_labels[self.number_of_hdd][3].setStyleSheet(
                'background-color: #00ff00')
            self.hdd_labels[self.number_of_hdd][4].setText(
                str(new_hdd.number_of_session))
            self.hdd_labels[self.number_of_hdd][4].setStyleSheet(
                'background-color: #00ff00')
            self.hdd_labels[self.number_of_hdd][4].setAlignment(
                QtCore.Qt.AlignCenter)
            self.hdd_labels[self.number_of_hdd][5].setPixmap(
                (QtGui.QPixmap('images/hdd.png')))
            self.number_of_hdd += 1

            print(f"Reading data from: {obj['disks'][1]['Drive Letter']}")
            logging.info(
                f'\n{current_date}\nAdded new disk to the shipment\nNew disk: {new_disk}\n'
            )
        else:
            print(Fore.RED + 'Wrong')
            print(Fore.RED + "Error you cannot add HDD")
            logging.info(f'\n{current_date}\nCannot add HDD')
            self.message_window.setText(
                'HDD already exists in the shipment or no HDD')
            x = self.message_window.exec()

    @pyqtSlot()
    def show_popup(self):
        res = QMessageBox.question(self, 'MessageBox', 'Are you sure?',
                                   QMessageBox.Yes | QMessageBox.Cancel,
                                   QMessageBox.Cancel)
        if res == QMessageBox.Yes:
            self.on_click()
        else:
            print('No')

    @pyqtSlot()
    def on_click(self):
        if len(self.driver_name_text.text()) == 0:
            self.message_window.setText('Add driver name')
            x = self.message_window.exec()
        else:
            try:
                print(Fore.GREEN + 'Sending')
                self.new_shipment['driver'] = self.driver_name_text.text()
                _, scode = send_to_heimdall(self.new_shipment)
                logging.info(
                    f'\n{current_date}\nShipement has been saved to db\nShipement: {self.new_shipment}\n'
                )
                self.message_window.setText(
                    f'Success! Your code: {self.generated_code}')
                x = self.message_window.exec()
                save_last_ship_to_file(
                    self.new_shipment['disks'][0]['carname'], current_date,
                    self.generated_code)
                print(Fore.GREEN + "Success")
                print(Fore.GREEN + "Shipment has been added to DB")
                print(Fore.GREEN +
                      "Ship's info has been added to lastship.txt as well")
                print(Fore.WHITE + "DONT FORGET YOUR CODE!")
            except:
                scode = '400'
                logging.info(f'\n{current_date}\nCan send data to db')
                self.message_window.setText(
                    'No connection or shipement exists in database')
                x = self.message_window.exec()
Пример #19
0
class MainWin(QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.setWindowTitle(win_title)
        self.resize(*win_size)
        self.save_dir = "Modified"

        self.create_widgets()
        self.layout_widgets()

        self.connects()

    def create_widgets(self):
        """Создаем виджеты для приложения"""
        self.lb_image = QLabel("Здесь будет картинка")
        self.btn_dir = QPushButton("Папка")
        self.lw_files = QListWidget()

        self.btn_left = QPushButton("Лево")
        self.btn_right = QPushButton("Право")
        self.btn_flip = QPushButton("Зеркало")
        self.btn_sharp = QPushButton("Резкость")
        self.btn_bw = QPushButton("Ч/б")

    def layout_widgets(self):
        """ Привязка виджетов к линиям и главному окну"""
        row = QHBoxLayout()
        col1 = QVBoxLayout()
        col2 = QVBoxLayout()
        col1.addWidget(self.btn_dir)
        col1.addWidget(self.lw_files)

        col2.addWidget(self.lb_image, 95)

        row_tools = QHBoxLayout()
        row_tools.addWidget(self.btn_left)
        row_tools.addWidget(self.btn_right)
        row_tools.addWidget(self.btn_flip)
        row_tools.addWidget(self.btn_sharp)
        row_tools.addWidget(self.btn_bw)
        col2.addLayout(row_tools)

        row.addLayout(col1, 20)
        row.addLayout(col2, 80)
        self.setLayout(row)

    def chooseWorkdir(self):
        """Функция выбора рабочей папки"""
        self.workdir = QFileDialog.getExistingDirectory()

    def filter(self):
        """Функция отбора имён файлов по расширениям"""
        self.filenames = []
        for filename in os.listdir(self.workdir):
            for ext in extensions:
                if filename.lower().endswith(ext):
                    self.filenames.append(filename)

    def showFilenamesList(self):
        """Функция-обработчик нажатия на кнопку «Папка»"""
        self.chooseWorkdir()
        if self.workdir:
            self.filter()
            self.lw_files.clear()
            self.lw_files.addItems(sorted(self.filenames))

    def loadImage(self):
        """Метод открывает файл и создает объект Image"""
        self.image_path = os.path.join(self.workdir, self.filename)
        self.image = Image.open(self.image_path)

    def showImage(self):
        self.lb_image.hide()
        pixmapimage = QPixmap(self.image_path)
        w, h = self.lb_image.width(), self.lb_image.height()
        pixmapimage = pixmapimage.scaled(w, h, Qt.KeepAspectRatio)
        self.lb_image.setPixmap(pixmapimage)
        self.lb_image.show()

    def showChosenImage(self):
        """Функция показывает картинку при выборе файла"""
        if self.lw_files.selectedItems():
            self.filename = self.lw_files.selectedItems()[0].text()
            self.loadImage()
            self.showImage()

    def createModified(self):
        path = os.path.join(self.workdir, self.save_dir)
        if not (os.path.exists(path) and os.path.isdir(path)):
            os.mkdir(path)

    def saveImage(self):
        """сохраняет копию файла в подпапке  Modified"""
        self.createModified()
        new_image_path = os.path.join(self.workdir, self.save_dir,
                                      self.filename)
        self.image.save(new_image_path)

    def do_bw(self):
        self.image = self.image.convert('L')
        self.saveImage()
        self.image_path = os.path.join(self.workdir, self.save_dir,
                                       self.filename)
        self.showImage()

    def connects(self):
        """Метод для привязки событий к обработчикам"""
        self.btn_dir.clicked.connect(self.showFilenamesList)
        self.lw_files.itemClicked.connect(self.showChosenImage)
        self.btn_bw.clicked.connect(self.do_bw)
Пример #20
0
class VictimWidget(AsyncWidget):
    on_host_click = pyqtSignal(Host)

    def __init__(self, interface: Interface, parent=None):
        super().__init__(parent)
        self.interface = interface
        self.list_elements = []
        self.setup()

    def setup(self):
        self.create_title()
        self.create_list()
        self.create_clear_button()
        self.create_layout()

    def create_title(self):
        self.title = QLabel('Victims')
        self.title.setAlignment(Qt.AlignmentFlag.AlignCenter)

    def create_list(self):
        self.host_list = QListWidget()
        self.host_list.itemDoubleClicked.connect(
            lambda item: self.on_host_click.emit(
                item.data(Qt.ItemDataRole.UserRole)))

    def create_clear_button(self):
        self.clear_button = QPushButton('Clear')
        self.clear_button.setIcon(QIcon('assets/clear.svg'))
        self.clear_button.clicked.connect(self.host_list.clear)
        self.clear_button.clicked.connect(lambda: self.list_elements.clear())

    def create_layout(self):
        layout = QVBoxLayout(self)
        layout.addWidget(self.title)
        layout.addWidget(self.clear_button)
        layout.addWidget(self.host_list)
        layout.setAlignment(Qt.AlignmentFlag.AlignCenter)

    def update_list(self):
        # remove duplicates
        self.list_elements = list(set(self.list_elements))
        self.list_elements = sort_hosts(self.list_elements)
        self.host_list.clear()

        for host in self.list_elements:
            item = QListWidgetItem(self.host_list)
            item.setData(Qt.ItemDataRole.DisplayRole, host.ip_address)
            item.setData(Qt.ItemDataRole.UserRole, host)

    def get_hosts(self):
        return self.list_elements

    def set_hosts(self, hosts: list[Host]):
        self.list_elements = hosts
        self.update_list()

    def add_host(self, host: Host):
        self.list_elements.append(host)
        self.update_list()

    hosts = property(get_hosts, set_hosts)
Пример #21
0
 def clear(self):
     self.__rowCode.clear()
     QListWidget.clear(self)
Пример #22
0
class GuiTabTemplate(QWidget):
    """General tab which enables import of DICOM files but also a set of distinct options such as viewing the
    metadata or displaying images in an external viewer and renaming folders"""

    def __init__(self, parent=None):
        super(GuiTabTemplate, self).__init__(parent)
        self.selected_subj_Gen = ''
        self.wdirTemplate = os.path.join(ROOTDIR, 'ext', 'templates')

        # General settings/variables/helper files needed needed at some point
        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['nifti']):
            self.niftidir = self.cfg['folders']['nifti']
        else:
            self.niftidir = FileOperations.set_wdir_in_config(self.cfg, foldername='nifti', init=True)
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        self.lay = QHBoxLayout(self)
        self.tab = QWidget()

        # Customize tab
        # ==============================    Tab 1 - General   ==============================
        self.tab.layout = QHBoxLayout()
        self.tab.setLayout(self.tab.layout)
        # ------------------------- Upper left part (Folder)  ------------------------- #
        self.FolderboxTab = QGroupBox("Directory (Templates)")
        self.HBoxUpperLeftTab = QVBoxLayout(self.FolderboxTab)

        self.dirTemplates = QLabel('wDIR: {}'.format(self.wdirTemplate))
        self.HBoxUpperLeftTab.addWidget(self.dirTemplates)

        self.btnChangeWdir = QPushButton('Change working directory')
        self.btnChangeWdir.setDisabled(True)

        self.btnReloadFilesTab = QPushButton('Reload files')
        self.btnReloadFilesTab.clicked.connect(self.run_reload_files)

        self.HBoxUpperLeftTab.addWidget(self.btnChangeWdir)
        self.HBoxUpperLeftTab.addWidget(self.btnReloadFilesTab)

        # ------------------------- Lower left part (Processing)  ------------------------- #
        self.ActionsTab = QGroupBox("Functions")
        self.HBoxLowerLeftTab = QVBoxLayout(self.ActionsTab)
        self.btn_new_default = QPushButton('Set new \ndefault')
        # self.btn_subj_details.setToolTip(setToolTips.subjectDetails()) TODO: new ToolTip needed
        self.btn_new_default.clicked.connect(self.redefineDefault)

        self.btn_viewer = QPushButton('View selected \nTemplate in viewer')
        # self.btn_viewer.setToolTip(setToolTips.displayFolderContent()) TODO: new ToolTip needed
        self.btn_viewer.clicked.connect(self.view_template)

        self.create_SST = QPushButton('Create Study-specific\ntemplate')
        # self.btn_renaming.setToolTip(setToolTips.renameFolders()) TODO: new ToolTip needed
        self.create_SST.clicked.connect(self.create_StudySpecificTemplate)

        self.HBoxLowerLeftTab.addWidget(self.btn_viewer)
        self.HBoxLowerLeftTab.addWidget(self.btn_new_default)
        self.HBoxLowerLeftTab.addWidget(self.create_SST)

        # -------------------- Right part (Subject list)  ----------------------- #
        self.listbox = QGroupBox('Available subjects')
        self.HBoxUpperRightTab = QVBoxLayout(self.listbox)
        self.availableTemplates = QListWidget()
        self.availableTemplates.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.availableTemplates.itemSelectionChanged.connect(self.change_list_item)
        itemsTab = set(FileOperations.list_files_in_folder(self.wdirTemplate))
        self.add_available_templates(self.availableTemplates, itemsTab)
        self.HBoxUpperRightTab.addWidget(self.availableTemplates)

        # Combine all Boxes for General Tab Layout
        self.LeftboxTab = QGroupBox()
        self.HBoxTabLeft = QVBoxLayout(self.LeftboxTab)
        self.HBoxTabLeft.addWidget(self.FolderboxTab)
        self.HBoxTabLeft.addStretch()
        self.HBoxTabLeft.addWidget(self.ActionsTab)

        self.tab.layout.addWidget(self.LeftboxTab)
        self.tab.layout.addWidget(self.listbox)

        self.lay.addWidget(self.tab)

    # ------------------------- Start with the functions for lists and buttons in this tab  ------------------------- #
    def run_reload_files(self):
        """Reloads files, e.g. after renaming them"""

        self.cfg = Configuration.load_config(self.cfg['folders']['rootdir'])
        self.availableTemplates.clear()
        itemsTab = set(FileOperations.list_files_in_folder(self.wdirTemplate))
        self.add_available_templates(self.availableTemplates, itemsTab)

    def change_list_item(self):
        """function intended to provide the item which is selected. As different tabs have a similar functioning, it is
         coded in a way that the sender is identified"""

        if self.sender() == self.availableTemplates:
            items = self.availableTemplates.selectedItems()
            self.selected_subj_Gen = []

            for i in range(len(items)):
                self.selected_subj_Gen.append(str(self.availableTemplates.selectedItems()[i].text()))

    def add_available_templates(self, sending_list, items, msg="yes"):
        """adds the available templates in the working directory into the items list;
        an error message is dropped if none available"""
        if len(items) == 0 and msg == "yes":
            buttonReply = QMessageBox.question(self, "No templates in folder", "There are no templates available "
                                               "in the directory: {}. Please make sure that at least the default "
                                               "ones are in this directory! Retry?".format(os.path.join(ROOTDIR, 'ext',
                                                                                                        'templates')),
                                               QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
            if buttonReply == QMessageBox.Yes:
                self.run_reload_files()
        else:
            sending_list.addItems(list(items))
            myFont = QtGui.QFont()
            myFont.setItalic(True)
            out = sending_list.findItems(os.path.basename(self.cfg['folders']['default_template']),
                                         QtCore.Qt.MatchExactly)
            out[0].setFont(myFont)

    def redefineDefault(self):
        """redefines which template is set as default on the right list and in the cfg-file"""

        if not self.selected_subj_Gen:
            Output.msg_box(text="No template selected. Please indicate new default one.", title="No data selected")
            return
        elif len(self.selected_subj_Gen) > 1:
            Output.msg_box(text="Please select only one image as default.", title="Too many templates selected")
            return
        else:
            default_template = [FileOperations.return_full_filename(self.wdirTemplate, x) for x in self.selected_subj_Gen]
            self.cfg['folders']['default_template'] = default_template[0]
            Configuration.save_config(ROOTDIR, self.cfg)

        self.run_reload_files()

    def create_StudySpecificTemplate(self):
        """Renames all folders with a similar prefix; After that manual reloading is necessary"""
        print('not yet implemented')

    def view_template(self):
        """this function opens a list dialog and enables selecting NIFTI files for e.g. check the content (identical
        function as in GUITabPreprocessANTs.py."""

        if not self.selected_subj_Gen:
            Output.msg_box(text="No image selected. Please indicate image(s) to load.", title="No templates selected")
            return
        else:
            template_list = [FileOperations.return_full_filename(self.wdirTemplate, x) for x in self.selected_subj_Gen]
            Imaging.load_imageviewer('itk-snap', template_list)  # to-date, only itk-snap available. could be changed
Пример #23
0
class ViewWidget(QWidget):
    tab_active = pyqtSignal()

    def __init__(self, iface, dock_widget: QDockWidget) -> None:
        super().__init__()
        self.iface = iface
        self.dock_widget = dock_widget

        self.vbox = QVBoxLayout()
        self.create_variable_selector()
        self.create_time_selector()
        self.create_extra_dim_selector()
        self.create_interp_input()
        self.create_dataset_selector()
        self.setLayout(self.vbox)

        self.datasets = {}  # type: Dict[str, Dataset]
        self.selected_dataset = None  # type: Optional[str]
        self.selected_variable = {}  # type: Dict[str,str]
        self.selected_time = {}  # type: Dict[str,int]
        self.selected_extra_dim = {}  # type: Dict[Tuple[str,str],int]

        self.pause_replace_layer = False

    def create_variable_selector(self) -> None:
        self.variable_selector = QListWidget()
        self.variable_selector.currentItemChanged.connect(
            self.on_variable_selected)
        hbox = QHBoxLayout()
        hbox.addWidget(self.variable_selector)
        self.vbox.addLayout(hbox)

    def create_time_selector(self) -> None:
        self.time_label = QLabel('Time: N/A')
        self.time_selector = QSlider(Qt.Horizontal)
        self.time_selector.setSingleStep(1)
        self.time_selector.setPageStep(1)
        self.time_selector.setMinimum(0)
        self.time_selector.valueChanged.connect(self.on_time_selected)
        self.vbox.addWidget(self.time_label)
        self.vbox.addWidget(self.time_selector)

    def create_extra_dim_selector(self) -> None:
        self.extra_dim_label = QLabel('N/A:')
        self.extra_dim_selector = QComboBox()
        self.extra_dim_selector.currentIndexChanged.connect(
            self.on_extra_dim_selected)
        hbox = QHBoxLayout()
        hbox.addWidget(self.extra_dim_label)
        hbox.addWidget(self.extra_dim_selector)
        hbox.setContentsMargins(0, 0, 0, 0)
        self.extra_dim_container = QWidget()
        self.extra_dim_container.setLayout(hbox)
        self.extra_dim_container.setHidden(True)
        self.vbox.addWidget(self.extra_dim_container)

    def create_interp_input(self) -> None:
        grid = QGridLayout()

        self.interp_vert_selector = add_grid_combobox(grid, 0,
                                                      'Vertical Variable')
        self.interp_input = add_grid_lineedit(grid,
                                              1,
                                              'Desired Level',
                                              QDoubleValidator(
                                                  0.0, 10000.0, 50),
                                              required=True)
        self.interp_input.returnPressed.connect(self.on_interp_btn_clicked)

        btn = QPushButton('Interpolate')
        btn.clicked.connect(self.on_interp_btn_clicked)
        grid.addWidget(btn, 2, 1)

        self.interp_container = QGroupBox('Interpolate Vertical Level')
        self.interp_container.setCheckable(True)
        self.interp_container.setChecked(False)
        self.interp_container.toggled.connect(self.on_interp_toggled)
        self.interp_container.setLayout(grid)
        self.interp_container.setHidden(True)
        self.vbox.addWidget(self.interp_container)

    def create_dataset_selector(self) -> None:
        dataset_label = QLabel('Dataset:')
        self.dataset_selector = QComboBox()
        self.dataset_selector.currentIndexChanged.connect(
            self.on_dataset_selected)
        hbox = QHBoxLayout()
        hbox.addWidget(dataset_label)
        hbox.addWidget(self.dataset_selector)
        self.vbox.addLayout(hbox)

    def add_dataset(self, path: str) -> None:
        variables = gis4wrf.core.get_supported_wrf_nc_variables(path)
        times = gis4wrf.core.get_wrf_nc_time_steps(path)
        extra_dims = gis4wrf.core.get_wrf_nc_extra_dims(path)
        dataset_name = os.path.basename(path)
        is_new_dataset = dataset_name not in self.datasets
        self.datasets[dataset_name] = Dataset(dataset_name, path, variables,
                                              times, extra_dims)
        if is_new_dataset:
            self.dataset_selector.addItem(dataset_name, dataset_name)
        self.select_dataset(dataset_name)

    def select_dataset(self, dataset_name: str) -> None:
        index = self.dataset_selector.findData(dataset_name)
        self.dataset_selector.setCurrentIndex(index)

    def init_variable_selector(self) -> None:
        dataset = self.dataset
        selected = self.selected_variable.get(dataset.name)
        self.variable_selector.clear()
        for var_name, variable in sorted(dataset.variables.items(),
                                         key=lambda v: v[1].label):
            item = QListWidgetItem(variable.label)
            item.setData(Qt.UserRole, var_name)
            self.variable_selector.addItem(item)
            if var_name == selected:
                item.setSelected(True)
        if selected is None:
            self.extra_dim_container.hide()

    def init_time_selector(self) -> None:
        dataset = self.dataset
        self.time_selector.setMaximum(len(dataset.times) - 1)
        selected_time = self.selected_time.get(dataset.name, 0)
        self.select_time(selected_time)
        # force label update in case the index didn't change during dataset change
        self.on_time_selected(selected_time)

    def select_time(self, index: int) -> None:
        self.time_selector.setValue(index)

    def init_extra_dim_selector(self) -> None:
        dataset = self.dataset
        variable = self.variable
        extra_dim_name = variable.extra_dim_name
        if extra_dim_name is None:
            self.extra_dim_container.hide()
            return
        # prevent double layer replace, already happens in on_variable_selected()
        self.pause_replace_layer = True
        extra_dim = dataset.extra_dims[extra_dim_name]
        selected_extra_dim = self.selected_extra_dim.get(
            (dataset.name, extra_dim_name), 0)
        self.extra_dim_label.setText(extra_dim.label + ':')
        self.extra_dim_selector.clear()
        for step in extra_dim.steps:
            self.extra_dim_selector.addItem(step)
        self.extra_dim_selector.setCurrentIndex(selected_extra_dim)
        self.extra_dim_container.show()
        self.pause_replace_layer = False

    def init_interp_input(self, dataset_init: bool) -> None:
        if dataset_init:
            self.interp_vert_selector.clear()
            has_vert = False
            for variable in sorted(self.dataset.variables.values(),
                                   key=lambda v: v.label):
                if variable.extra_dim_name != 'bottom_top':
                    continue
                has_vert = True
                self.interp_vert_selector.addItem(variable.label,
                                                  variable.name)
            if not has_vert:
                self.extra_dim_container.setEnabled(True)
                self.interp_container.hide()
        else:
            variable = self.variable
            extra_dim_name = variable.extra_dim_name
            if extra_dim_name != 'bottom_top':
                self.interp_container.hide()
                return
            self.interp_container.show()

    def on_dataset_selected(self, index: int) -> None:
        self.init_variable_selector()
        self.init_time_selector()
        self.init_interp_input(True)

        previous_dataset = self.selected_dataset
        if previous_dataset is not None:
            gis4wrf.plugin.geo.remove_group(previous_dataset)
        self.selected_dataset = self.dataset_name

    def on_variable_selected(self, current: Optional[QListWidgetItem],
                             previous: Optional[QListWidgetItem]) -> None:
        if current is None:
            return
        dataset = self.dataset
        var_name = current.data(Qt.UserRole)
        assert var_name == self.var_name
        self.selected_variable[dataset.name] = var_name
        self.init_extra_dim_selector()
        self.init_interp_input(False)
        self.replace_variable_layer()
        self.select_time_band_in_variable_layers()

    def on_time_selected(self, index: int) -> None:
        dataset = self.dataset
        self.selected_time[dataset.name] = index
        self.time_label.setText('Time: ' + dataset.times[index])
        self.select_time_band_in_variable_layers()

    def on_extra_dim_selected(self, index: int) -> None:
        if index == -1:
            # happens when clearing the dropdown entries
            return
        variable = self.variable
        extra_dim_name = variable.extra_dim_name
        self.selected_extra_dim[(self.dataset_name, extra_dim_name)] = index
        self.replace_variable_layer()
        self.select_time_band_in_variable_layers()

    def on_interp_toggled(self, enabled: True) -> None:
        self.extra_dim_container.setEnabled(not enabled)
        self.replace_variable_layer()

    def on_interp_btn_clicked(self) -> None:
        self.replace_variable_layer()
        self.select_time_band_in_variable_layers()

    def replace_variable_layer(self) -> None:
        if self.pause_replace_layer:
            return
        if self.interp_enabled and self.interp_level is None:
            return
        dataset = self.dataset
        variable = self.variable
        extra_dim_index = self.extra_dim_index
        interp_level = self.interp_level
        interp_vert_name = self.interp_vert_name
        if interp_level is not None:
            extra_dim_index = None
        uri, dispose = gis4wrf.core.convert_wrf_nc_var_to_gdal_dataset(
            dataset.path, variable.name, extra_dim_index, interp_level,
            interp_vert_name)
        layer = gis4wrf.plugin.geo.load_layers(
            [(uri, variable.label, variable.name)],
            group_name=dataset.name,
            visible=True)[0]
        dispose_after_delete(layer, dispose)

    def select_time_band_in_variable_layers(self) -> None:
        dataset = self.dataset
        time_idx = self.time_index
        layers = gis4wrf.plugin.geo.get_raster_layers_in_group(dataset.name)
        for layer in layers:
            var_name = layer.shortName()
            if var_name in dataset.variables:
                gis4wrf.plugin.geo.switch_band(layer, time_idx)

    @property
    def dataset_name(self) -> str:
        return self.dataset_selector.currentData()

    @property
    def var_name(self) -> str:
        return self.variable_selector.currentItem().data(Qt.UserRole)

    @property
    def time_index(self) -> int:
        return self.time_selector.value()

    @property
    def extra_dim_index(self) -> Optional[int]:
        if self.variable.extra_dim_name is None:
            return None
        index = self.extra_dim_selector.currentIndex()
        assert index != -1
        return index

    @property
    def interp_enabled(self):
        return self.interp_container.isVisible(
        ) and self.interp_container.isChecked()

    @property
    def interp_vert_name(self):
        if not self.interp_enabled:
            return None
        return self.interp_vert_selector.currentData()

    @property
    def interp_level(self) -> Optional[float]:
        if not self.interp_enabled:
            return None
        if not self.interp_input.is_valid():
            return None
        return self.interp_input.value()

    @property
    def dataset(self) -> Dataset:
        return self.datasets[self.dataset_name]

    @property
    def variable(self) -> WRFNetCDFVariable:
        return self.dataset.variables[self.var_name]
Пример #24
0
class CommonDoublePanelWidget(DoublePanelWidget):
    def __init__(self, parent, label=''):
        super().__init__(parent)

        self.secondary_label = label
        self.secondary_labels = []
        self.reach_name = ''
        self.qlw_variables = QListWidget()
        self.qlw_secondary_list = QListWidget()
        self.qcbx_reaches = QComboBox()

        self.create_layout()
        self.on_show()

    def on_show(self):
        super().on_show()
        if len(self.qlw_variables.selectedItems()) == 1:
            self.axes.set_ylabel(self.qlw_variables.selectedItems()[0].text())
        else:
            self.axes.set_ylabel('Valeur')

    def fill_reach_list(self):
        self.qcbx_reaches.clear()
        for reach_name in self.parent.data.model.keys():
            self.qcbx_reaches.addItem(reach_name)

    def fill_variables_list(self):
        self.qlw_variables.clear()
        for name in self.parent.data.variable_names:
            self.qlw_variables.addItem(name)

    def fill_secondary_list(self):
        self.qlw_secondary_list.clear()
        for label in self.secondary_labels:
            self.qlw_secondary_list.addItem(str(label))

    def create_layout(self):
        self.qcbx_reaches.currentIndexChanged.connect(self.reach_changed)

        self.qlw_variables.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.qlw_variables.itemSelectionChanged.connect(self.on_show)
        self.qlw_secondary_list.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.qlw_secondary_list.itemSelectionChanged.connect(self.on_show)

        self.qvb_options.addWidget(QLabel('River reach:'))
        self.qvb_options.addWidget(self.qcbx_reaches)
        self.qvb_options.addWidget(QLabel('Variables:'))
        self.qvb_options.addWidget(self.qlw_variables, 20)
        self.qvb_options.addWidget(QLabel(self.secondary_label))
        self.qvb_options.addWidget(self.qlw_secondary_list, 20)
        super().create_layout()

    def set_default_selection(self):
        # Select by default first variable and first time
        if self.qlw_variables.count() > 0:
            self.qlw_variables.item(0).setSelected(True)
        if self.qlw_secondary_list.count() > 0:
            self.qlw_secondary_list.item(0).setSelected(True)

    def reach_changed(self):
        self.reach_name = self.qcbx_reaches.currentText()
Пример #25
0
class SubSheet(SimpleBlackbox):
    author = "DrLuke"
    name = "Subsheet"
    modulename = "subsheet"

    Category = ["Builtin"]

    placeable = True

    implementation = SubSheetImplementation

    def __init__(self, *args, **kwargs):
        self.ownsheet = None
        self.sheets = None
        self.selectedSheet = None
        self.listSheetItems = {}

        super(SubSheet, self).__init__(*args, **kwargs)

        self.propertiesWidget = QWidget()

        self.vlayout = QVBoxLayout()

        self.listWidget = QListWidget()
        self.listWidget.itemClicked.connect(self.listClicked)
        self.vlayout.addWidget(self.listWidget)

        self.vlayout.addItem(QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Expanding))

        self.propertiesWidget.setLayout(self.vlayout)

    def getPropertiesWidget(self):
        return self.propertiesWidget

    def updateSheets(self):
        if self.sheets is not None and self.ownsheet is not None:
            self.listSheetItems = {}
            self.listWidget.clear()
            for sheetId in self.sheets:
                if not sheetId == self.ownsheet:
                    newItem = QListWidgetItem(self.sheets[sheetId])
                    newItem.setToolTip(str(sheetId))
                    newItem.setData(Qt.UserRole, sheetId)
                    self.listSheetItems[sheetId] = newItem
                    self.listWidget.addItem(newItem)

                    if sheetId == self.selectedSheet:
                        boldFont = QFont()
                        boldFont.setBold(True)
                        newItem.setFont(boldFont)

    def listClicked(self, item):
        normalFont = QFont()
        boldFont = QFont()
        boldFont.setBold(True)

        for i in range(self.listWidget.count()):
            itemnormal = self.listWidget.item(i)
            itemnormal.setFont(normalFont)

        self.selectedSheet = item.data(Qt.UserRole)
        self.sendDataToImplementations({"subsheetid": self.selectedSheet})
        item.setFont(boldFont)

    def serialize(self):
        return {"subsheetid": self.selectedSheet}

    def deserialize(self, data):
        if data is not None:
            if "subsheetid" in data:
                self.selectedSheet = data["subsheetid"]
                self.sendDataToImplementations({"subsheetid": self.selectedSheet})

    def selectedChanged(self, state):
        if state:
            self.mainRect.setPen(QPen(Qt.red))
        else:
            self.mainRect.setPen(QPen(Qt.blue))

    def defineIO(self):
        self.addInput(execType, "execInit", "Execute Init")
        self.addInput(execType, "execLoop", "Execute Loop")

        self.addOutput(execType, "ExecInitOut", "Init Done")
        self.addOutput(execType, "ExecLoopOut", "Loop Done")
Пример #26
0
class GlyphSetTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.name = self.tr("Glyph sets")

        self.defaultGlyphSetBox = QCheckBox(self.tr("Default glyph set:"),
                                            self)
        self.defaultGlyphSetDrop = QComboBox(self)
        self.defaultGlyphSetBox.toggled.connect(self.toggleGlyphSetDrop)

        self.glyphSetList = QListWidget(self)
        self.glyphSetList.setSortingEnabled(True)
        self.glyphSetContents = QPlainTextEdit(self)
        self.glyphSetList.currentItemChanged.connect(
            self.updateGlyphSetContents)
        self.glyphSetList.itemChanged.connect(self.renameGlyphSet)
        self._cachedName = None
        splitter = QSplitter(self)
        splitter.addWidget(self.glyphSetList)
        splitter.addWidget(self.glyphSetContents)
        self.addGlyphSetButton = QPushButton(self)
        self.addGlyphSetButton.setIcon(icons.i_plus())
        self.addGlyphSetButton.clicked.connect(lambda: self.addGlyphSet())
        self.removeGlyphSetButton = QPushButton(self)
        self.removeGlyphSetButton.setIcon(icons.i_minus())
        self.removeGlyphSetButton.clicked.connect(self.removeGlyphSet)
        self.importButton = QPushButton(self.tr("Import"), self)
        importMenu = QMenu(self)
        importMenu.addAction(self.tr("Import from Current Font"),
                             self.importFromCurrentFont)
        self.importButton.setMenu(importMenu)
        self.glyphListBox = QCheckBox(self.tr("Glyph list path:"), self)
        self.glyphListEdit = QLineEdit(self)
        self.glyphListEdit.setReadOnly(True)
        self.glyphListButton = QPushButton(self.tr("Browse…"), self)
        self.glyphListButton.clicked.connect(self.getGlyphList)
        self.glyphListBox.toggled.connect(self.glyphListEdit.setEnabled)
        self.glyphListBox.toggled.connect(self.glyphListButton.setEnabled)

        buttonsLayout = QHBoxLayout()
        buttonsLayout.addWidget(self.addGlyphSetButton)
        buttonsLayout.addWidget(self.removeGlyphSetButton)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        buttonsLayout.addWidget(spacer)
        buttonsLayout.addWidget(self.importButton)

        firstLayout = QGridLayout()
        line = 0
        firstLayout.addWidget(self.defaultGlyphSetBox, line, 0, 1, 2)
        firstLayout.addWidget(self.defaultGlyphSetDrop, line, 3, 1, 3)
        line += 1
        firstLayout.addWidget(splitter, line, 0, 1, 6)
        line += 1
        firstLayout.addLayout(buttonsLayout, line, 0, 1, 3)
        secondLayout = QHBoxLayout()
        secondLayout.addWidget(self.glyphListBox)
        secondLayout.addWidget(self.glyphListEdit)
        secondLayout.addWidget(self.glyphListButton)
        mainLayout = QVBoxLayout(self)
        mainLayout.addLayout(firstLayout)
        mainLayout.addLayout(secondLayout)
        self.setLayout(mainLayout)

        self.readSettings()

    def addGlyphSet(self, glyphNames=[], glyphSetName=None):
        if glyphSetName is None:
            glyphSetName = self.tr("New glyph set")
        if glyphSetName in self.glyphSets:
            index = 1
            while "%s %d" % (glyphSetName, index) in self.glyphSets:
                index += 1
            glyphSetName = "%s %d" % (glyphSetName, index)
        self.glyphSets[glyphSetName] = glyphNames
        item = QListWidgetItem(glyphSetName, self.glyphSetList)
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self.glyphSetList.setCurrentItem(item)
        self.glyphSetList.editItem(item)
        self.removeGlyphSetButton.setEnabled(True)

    def removeGlyphSet(self):
        i = self.glyphSetList.currentRow()
        text = self.glyphSetList.takeItem(i).text()
        del self.glyphSets[text]
        if self.glyphSetList.count() < 2:
            self.removeGlyphSetButton.setEnabled(False)

    def renameGlyphSet(self):
        newKey = self.glyphSetList.currentItem()
        if newKey is None:
            return
        newKey = newKey.text()
        self.glyphSets[newKey] = self.glyphSets[self._cachedName]
        del self.glyphSets[self._cachedName]

    def importFromCurrentFont(self):
        font = QApplication.instance().currentFont()
        name = f"{font.info.familyName} {font.info.styleName}"
        self.addGlyphSet(font.glyphOrder, name)

    def toggleGlyphSetDrop(self):
        sender = self.sender()
        self.defaultGlyphSetDrop.setEnabled(sender.isChecked())

    def updateGlyphSetContents(self, current, previous):
        # store content of the textEdit in the glyphSet dict
        if previous is not None:
            glyphNames = self.glyphSetContents.toPlainText().split()
            self.glyphSets[previous.text()] = glyphNames
        # now update the text edit to current glyphSet
        glyphSetName = current.text()
        text = " ".join(self.glyphSets[glyphSetName])
        self.glyphSetContents.setPlainText(text)
        # cache current name for renames
        self._cachedName = glyphSetName

    def getGlyphList(self):
        fileFormats = (
            self.tr("Text file {}").format("(*.txt)"),
            self.tr("All files {}").format("(*.*)"),
        )
        path, _ = QFileDialog.getOpenFileName(self, self.tr("Open File"), "",
                                              ";;".join(fileFormats))
        if path:
            self.glyphListEdit.setText(path)

    def readSettings(self):
        defaultGlyphSet = settings.defaultGlyphSet()
        self.defaultGlyphSetBox.setChecked(len(defaultGlyphSet))

        self.glyphSets = settings.readGlyphSets()
        self.defaultGlyphSetDrop.clear()
        self.defaultGlyphSetDrop.addItems(self.glyphSets.keys())

        self.glyphSetList.clear()
        glyphSetNames = self.glyphSets.keys()
        # Normally we should be enforcing this rather decently in the interface
        # already
        if glyphSetNames:
            for glyphSetName in glyphSetNames:
                item = QListWidgetItem(glyphSetName, self.glyphSetList)
                item.setFlags(item.flags() | Qt.ItemIsEditable)
            self.glyphSetList.setCurrentRow(0)
        self.removeGlyphSetButton.setEnabled(len(self.glyphSets) > 1)

        glyphListPath = settings.glyphListPath()
        self.glyphListBox.setChecked(bool(glyphListPath))
        self.glyphListEdit.setEnabled(bool(glyphListPath))
        self.glyphListEdit.setText(glyphListPath)
        self.glyphListButton.setEnabled(bool(glyphListPath))

    def writeSettings(self):
        # store content of the textEdit in the glyphSet dict
        glyphNames = self.glyphSetContents.toPlainText().split()
        currentGlyphSet = self.glyphSetList.currentItem().text()
        self.glyphSets[currentGlyphSet] = glyphNames

        settings.writeGlyphSets(self.glyphSets)
        if not self.defaultGlyphSetBox.isChecked():
            settings.setDefaultGlyphSet(None)
        else:
            defaultGlyphSet = self.defaultGlyphSetDrop.currentText()
            settings.setDefaultGlyphSet(defaultGlyphSet)
        if not self.glyphListBox.isChecked():
            settings.setGlyphListPath(None)
        else:
            glyphListPath = self.glyphListEdit.text()
            if glyphListPath:
                settings.setGlyphListPath(glyphListPath)
                QApplication.instance().loadGlyphList()
Пример #27
0
class CodeCompletionWidget(QFrame):

    def __init__(self, editor):
        super(CodeCompletionWidget, self).__init__(
            None, Qt.FramelessWindowHint | Qt.ToolTip)
        self._editor = editor
        self._revision = 0
        self._block = 0
        self.stack_layout = QStackedLayout(self)
        self.stack_layout.setContentsMargins(0, 0, 0, 0)
        self.stack_layout.setSpacing(0)
        self.completion_list = QListWidget()
        self.completion_list.setMinimumHeight(200)
        self.completion_list.setAlternatingRowColors(True)
        self._list_index = self.stack_layout.addWidget(self.completion_list)

        self._icons = {'a': resources.IMAGES['attribute'],
                       'f': resources.IMAGES['function'],
                       'c': resources.IMAGES['class'],
                       'm': resources.IMAGES['module']}

        self.cc = code_completion.CodeCompletion()
        self._completion_results = {}
        self._prefix = ''
        self.setVisible(False)
        self.source = ''
        self._key_operations = {
            Qt.Key_Up: self._select_previous_row,
            Qt.Key_Down: self._select_next_row,
            Qt.Key_PageUp: (lambda: self._select_previous_row(6)),
            Qt.Key_PageDown: (lambda: self._select_next_row(6)),
            Qt.Key_Right: lambda: None,
            Qt.Key_Left: lambda: None,
            Qt.Key_Enter: self.pre_key_insert_completion,
            Qt.Key_Return: self.pre_key_insert_completion,
            Qt.Key_Tab: self.pre_key_insert_completion,
            Qt.Key_Space: self.hide_completer,
            Qt.Key_Escape: self.hide_completer,
            Qt.Key_Backtab: self.hide_completer,
            Qt.NoModifier: self.hide_completer,
            Qt.ShiftModifier: self.hide_completer,
        }

        self.desktop = QApplication.instance().desktop()

        self.completion_list.itemClicked['QListWidgetItem*'].connect(self.pre_key_insert_completion)
        self._editor.document().cursorPositionChanged['const QTextCursor &'].connect(self.update_metadata)

    def _select_next_row(self, move=1):
        new_row = self.completion_list.currentRow() + move
        if new_row < self.completion_list.count():
            self.completion_list.setCurrentRow(new_row)
        else:
            self.completion_list.setCurrentRow(0)
        return True

    def _select_previous_row(self, move=1):
        new_row = self.completion_list.currentRow() - move
        if new_row >= 0:
            self.completion_list.setCurrentRow(new_row)
        else:
            self.completion_list.setCurrentRow(
                self.completion_list.count() - move)
        return True

    def update_metadata(self, cursor):
        if settings.CODE_COMPLETION:
            if self._editor.document().revision() != self._revision and \
               cursor.block().blockNumber() != self._block:
                source = self._editor.get_text()
                source = source.encode(self._editor.encoding)
                self.cc.analyze_file(self._editor.ID, source,
                                     self._editor.indent, self._editor.useTabs)
                self._revision = self._editor.document().revision()
                self._block = cursor.block().blockNumber()

    def insert_completion(self, insert, type_=ord('a')):
        if insert != self._prefix:
            closing = ''
            if type_ in (ord('f'), ord('c')):
                closing = '()'
            extra = len(self._prefix) - len(insert)
            insertion = '%s%s' % (insert[extra:], closing)
            self._editor.textCursor().insertText(insertion)
        self.hide_completer()

    def _get_geometry(self):
        cr = self._editor.cursorRect()
        desktop_geometry = self.desktop.availableGeometry(self._editor)
        point = self._editor.mapToGlobal(cr.topLeft())
        cr.moveTopLeft(point)
        #Check new position according desktop geometry
        width = (self.completion_list.sizeHintForColumn(0) +
                 self.completion_list.verticalScrollBar().sizeHint().width() +
                 10)
        height = 200
        orientation = (point.y() + height) < desktop_geometry.height()
        if orientation:
            cr.moveTop(cr.bottom())
        cr.setWidth(width)
        cr.setHeight(height)
        if not orientation:
            cr.moveBottom(cr.top())
        xpos = desktop_geometry.width() - (point.x() + width)
        if xpos < 0:
            cr.moveLeft(cr.left() + xpos)
        return cr

    def complete(self, results):
        self.add_list_items(results)
        self.completion_list.setCurrentRow(0)
        cr = self._get_geometry()
        self.setGeometry(cr)
        self.completion_list.updateGeometries()
        self.show()

    def add_list_items(self, proposals):
        self.completion_list.clear()
        for p in proposals:
            self.completion_list.addItem(
                QListWidgetItem(
                    QIcon(
                        self._icons.get(p[0], resources.IMAGES['attribute'])),
                    p[1], type=ord(p[0])))

    def set_completion_prefix(self, prefix, valid=True):
        self._prefix = prefix
        proposals = []
        proposals += [('m', item)
                      for item in self._completion_results.get('modules', [])
                      if item.startswith(prefix)]
        proposals += [('c', item)
                      for item in self._completion_results.get('classes', [])
                      if item.startswith(prefix)]
        proposals += [('a', item)
                      for item in self._completion_results.get(
                          'attributes', [])
                      if item.startswith(prefix)]
        proposals += [('f', item)
                      for item in self._completion_results.get('functions', [])
                      if item.startswith(prefix)]
        if proposals and valid:
            self.complete(proposals)
        else:
            self.hide_completer()

    def _invalid_completion_position(self):
        result = False
        cursor = self._editor.textCursor()
        cursor.movePosition(QTextCursor.StartOfLine,
                            QTextCursor.KeepAnchor)
        selection = cursor.selectedText()[:-1].split(' ')
        if len(selection) == 0 or selection[-1] == '' or \
           selection[-1].isdigit():
            result = True
        return result

    def fill_completer(self, force_completion=False):
        if not force_completion and (self._editor.cursor_inside_string() or
           self._editor.cursor_inside_comment() or
           self._invalid_completion_position()):
            return
        source = self._editor.get_text()
        source = source.encode(self._editor.encoding)
        offset = self._editor.textCursor().position()
        results = self.cc.get_completion(source, offset)
        self._completion_results = results
        if force_completion:
            cursor = self._editor.textCursor()
            cursor.movePosition(QTextCursor.StartOfWord,
                                QTextCursor.KeepAnchor)
            prefix = cursor.selectedText()
        else:
            prefix = self._editor._text_under_cursor()
        self.set_completion_prefix(prefix)

    def hide_completer(self):
        self._prefix = ''
        self.hide()

    def pre_key_insert_completion(self):
        type_ = ord('a')
        current = self.completion_list.currentItem()
        insert = current.text()
        if not insert.endswith(')'):
            type_ = current.type()
        self.insert_completion(insert, type_)
        self.hide_completer()
        return True

    def process_pre_key_event(self, event):
        if not self.isVisible() or self._editor.lang != "python":
            return False
        skip = self._key_operations.get(event.key(), lambda: False)()
        self._key_operations.get(event.modifiers(), lambda: False)()
        if skip is None:
            skip = False
        return skip

    def process_post_key_event(self, event):
        if not settings.CODE_COMPLETION or self._editor.lang != "python":
            return
        if self.isVisible():
            source = self._editor.get_text()
            source = source.encode(self._editor.encoding)
            offset = self._editor.textCursor().position()
            prefix, valid = self.cc.get_prefix(source, offset)
            self.set_completion_prefix(prefix, valid)
            self.completion_list.setCurrentRow(0)
        force_completion = (event.key() == Qt.Key_Space and
                            event.modifiers() == Qt.ControlModifier)
        if event.key() == Qt.Key_Period or force_completion:
            self.fill_completer(force_completion)
Пример #28
0
class MainWindow(QMainWindow):
    def __init__(self, flags, *args, **kwargs):
        super().__init__(flags, *args, **kwargs)

        self.comps = dict()

        self.setFixedSize(*window_size)
        self.setWindowTitle('Pong')

        self.stack = QStackedWidget(self)
        self.setCentralWidget(self.stack)

        self.highscore_list = QListWidget()

        self.pong_game = SoloMode()
        self.pong_game.finished_signal.connect(self.finish_game)

        self.home_view = QWidget()
        self.pong_view = self.pong_game.scene_view.view

        self.setup_home_view()

        self.stack.addWidget(self.home_view)
        self.stack.addWidget(self.pong_view)

        self.stack.setCurrentWidget(self.home_view)

    # noinspection PyArgumentList
    def setup_home_view(self):
        res = QWidget()
        box_layout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
        form = QWidget()
        form_layout = QFormLayout()

        self.comps["status"] = QLabel()
        self.comps["status"].setText("False")
        self.comps["status"].setStyleSheet('background-color: red')
        form_layout.addRow("Receiving", self.comps["status"])

        self.comps["name"] = QLineEdit()
        form_layout.addRow("Full Name", self.comps["name"])

        self.comps["age"] = QLineEdit()
        form_layout.addRow("Age", self.comps["age"])

        self.comps["gender"] = QComboBox()
        self.comps["gender"].addItems(["male", "female", "other"])
        form_layout.addRow("Gender", self.comps["gender"])

        self.comps["is_real"] = QCheckBox()
        form_layout.addRow("Real data", self.comps["is_real"])

        button = QPushButton("Play Solo")
        button.clicked.connect(self.play_solo)
        form_layout.addRow("", button)
        form.setLayout(form_layout)

        box_layout.addWidget(form, stretch=2)

        self.highscore_list.addItems(fetch_highscore())

        box_layout.addWidget(self.highscore_list, stretch=1)

        res.setLayout(box_layout)
        res.setFixedSize(*window_size)
        self.home_view = res

    def finish_game(self):
        self.pong_game.stop()
        self.stack.setCurrentWidget(self.home_view)
        self.update_highscore_list()

    def play_solo(self):
        name = self.comps["name"].text()
        age = self.comps["age"].text()
        gender = self.comps["gender"].currentText()

        if not name:
            name = "Olav Ljosland"

        if not age:
            age = "24"

        sys_manager.person = Person.create_or_fetch(name, age, gender)
        sys_manager.is_real_data = bool(self.comps["is_real"].checkState())

        self.stack.setCurrentWidget(self.pong_view)
        self.pong_game.start()

    def update_status_indicator(self, receiving_samples):
        self.comps["status"].setText(str(receiving_samples))
        if receiving_samples:
            self.comps["status"].setStyleSheet('background-color: green')
        else:
            self.comps["status"].setStyleSheet('background-color: red')

    def update_highscore_list(self):
        self.highscore_list.clear()
        self.highscore_list.addItems(fetch_highscore())
class GstMediaSettings(SettingsPage):

    Name = 'Media Settings'

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.setLayout(QGridLayout())

        self._pages = []
        self._current_page = None
        self._settings = {}
        self._check = False

        self.listWidget = QListWidget(self)
        self.layout().addWidget(self.listWidget, 0, 0)

        self.pipeButton = QPushButton('Change Pipe', self)
        self.layout().addWidget(self.pipeButton, 1, 0)

        self.layout().setColumnStretch(0, 2)
        self.layout().setColumnStretch(1, 5)

        self.listWidget.currentItemChanged.connect(self.__change_page)
        self.pipeButton.clicked.connect(self.__edit_pipe)

    def load_settings(self, settings):
        settings = settings.get('_media_', {})
        # Create a local copy of the configuration
        self._settings = deepcopy(settings)

        # Create the widgets
        pages = pages_by_element_name()
        for element in settings.get('pipe', ()):
            page = pages.get(element)

            if page is not None:
                page = page(element, parent=self)
                page.load_settings(settings.get('elements', {}))
                self._pages.append(page)

                item = QListWidgetItem(page.NAME)
                self.listWidget.addItem(item)

            self.listWidget.setCurrentRow(0)

    def get_settings(self):
        settings = {'elements': {}}

        for page in self._pages:
            settings['elements'].update(page.get_settings())

        # The pipeline is returned only if check is disabled
        if not self._check:
            settings['pipe'] = self._settings['pipe']

        return {'_media_': settings}

    def enable_check(self, enabled):
        self._check = enabled
        for page in self._pages:
            if isinstance(page, SettingsPage):
                page.enable_check(enabled)

    def __change_page(self, current, previous):
        if current is None:
            current = previous

        if self._current_page is not None:
            self.layout().removeWidget(self._current_page)
            self._current_page.hide()

        self._current_page = self._pages[self.listWidget.row(current)]
        self._current_page.show()
        self.layout().addWidget(self._current_page, 0, 1, 2, 1)

    def __edit_pipe(self):
        # Backup the settings
        self._settings.update(self.get_settings()['_media_'])

        # Show the dialog
        dialog = GstPipeEditDialog(self._settings.get('pipe', ()), parent=self)

        if dialog.exec_() == dialog.Accepted:
            # Reset the view
            self.listWidget.clear()
            if self._current_page is not None:
                self.layout().removeWidget(self._current_page)
                self._current_page.hide()
            self._current_page = None
            self._pages.clear()

            # Reload with the new pipeline
            self._settings['pipe'] = dialog.get_pipe()

            self.load_settings({'_media_': self._settings})
            self.enable_check(self._check)
Пример #30
0
class ErrorsWidget(QWidget):

###############################################################################
# ERRORS WIDGET SIGNALS
###############################################################################
    """
    pep8Activated(bool)
    lintActivated(bool)
    """

    pep8Activated = pyqtSignal(bool)
    lintActivated = pyqtSignal(bool)

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

    def __init__(self):
        super(ErrorsWidget, self).__init__()
        self.pep8 = None
        self._outRefresh = True

        vbox = QVBoxLayout(self)
        self.listErrors = QListWidget()
        self.listErrors.setSortingEnabled(True)
        self.listPep8 = QListWidget()
        self.listPep8.setSortingEnabled(True)
        hbox_lint = QHBoxLayout()
        if settings.FIND_ERRORS:
            self.btn_lint_activate = QPushButton(_translate("ErrorsWidget", "Lint: ON"))
        else:
            self.btn_lint_activate = QPushButton(_translate("ErrorsWidget", "Lint: OFF"))
        self.errorsLabel = QLabel(_translate("ErrorsWidget", "Static Errors: %s") % 0)
        hbox_lint.addWidget(self.errorsLabel)
        hbox_lint.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        hbox_lint.addWidget(self.btn_lint_activate)
        vbox.addLayout(hbox_lint)
        vbox.addWidget(self.listErrors)
        hbox_pep8 = QHBoxLayout()
        if settings.CHECK_STYLE:
            self.btn_pep8_activate = QPushButton(_translate("ErrorsWidget", "PEP8: ON"))
        else:
            self.btn_pep8_activate = QPushButton(_translate("ErrorsWidget", "PEP8: OFF"))
        self.pep8Label = QLabel(_translate("ErrorsWidget", "PEP8 Errors: %s") % 0)
        hbox_pep8.addWidget(self.pep8Label)
        hbox_pep8.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        hbox_pep8.addWidget(self.btn_pep8_activate)
        vbox.addLayout(hbox_pep8)
        vbox.addWidget(self.listPep8)

        self.listErrors.itemSelectionChanged.connect(self.errors_selected)
        self.listPep8.itemSelectionChanged.connect(self.pep8_selected)
        self.btn_lint_activate.clicked['bool'].connect(self.errors_selected)
        self.btn_pep8_activate.clicked['bool'].connect(self._turn_on_off_pep8)

    def _turn_on_off_lint(self):
        """Change the status of the lint checker state."""
        settings.FIND_ERRORS = not settings.FIND_ERRORS
        if settings.FIND_ERRORS:
            self.btn_lint_activate.setText(_translate("ErrorsWidget", "Lint: ON"))
        else:
            self.btn_lint_activate.setText(_translate("ErrorsWidget", "Lint: OFF"))
        self.lintActivated.emit(settings.FIND_ERRORS)

    def _turn_on_off_pep8(self):
        """Change the status of the lint checker state."""
        settings.CHECK_STYLE = not settings.CHECK_STYLE
        if settings.CHECK_STYLE:
            self.btn_pep8_activate.setText(_translate("ErrorsWidget", "PEP8: ON"))
        else:
            self.btn_pep8_activate.setText(_translate("ErrorsWidget", "PEP8: OFF"))
        self.pep8Activated.emit(settings.CHECK_STYLE)

    def errors_selected(self):
        editorWidget = main_container.MainContainer().get_actual_editor()
        if editorWidget and self._outRefresh:
            lineno = int(self.listErrors.currentItem().data(Qt.UserRole))
            editorWidget.jump_to_line(lineno)
            editorWidget.setFocus()

    def pep8_selected(self):
        editorWidget = main_container.MainContainer().get_actual_editor()
        if editorWidget and self._outRefresh:
            lineno = int(self.listPep8.currentItem().data(Qt.UserRole))
            editorWidget.jump_to_line(lineno)
            editorWidget.setFocus()

    def refresh_lists(self, errors, pep8):
        self._outRefresh = False
        self.listErrors.clear()
        self.listPep8.clear()
        for lineno in errors.errorsSummary:
            linenostr = 'L%s\t' % str(lineno + 1)
            for data in errors.errorsSummary[lineno]:
                item = QListWidgetItem(linenostr + data)
                item.setToolTip(linenostr + data)
                item.setData(Qt.UserRole, lineno)
                self.listErrors.addItem(item)
        self.errorsLabel.setText(_translate("ErrorsWidget", "Static Errors: %s") %
            len(errors.errorsSummary))
        for lineno in pep8.pep8checks:
            linenostr = 'L%s\t' % str(lineno + 1)
            for data in pep8.pep8checks[lineno]:
                item = QListWidgetItem(linenostr + data.split('\n')[0])
                item.setToolTip(linenostr + data.split('\n')[0])
                item.setData(Qt.UserRole, lineno)
                self.listPep8.addItem(item)
        self.pep8Label.setText(_translate("ErrorsWidget", "PEP8 Errors: %s") %
            len(pep8.pep8checks))
        self._outRefresh = True

    def clear(self):
        """
        Clear the widget
        """
        self.listErrors.clear()
        self.listPep8.clear()
Пример #31
0
class FindDialog(QDialog):
    alphabetical = [dict(type="alphabetical", allowPseudoUnicode=True)]

    def __init__(self, currentGlyph, parent=None):
        super().__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle(self.tr("Find…"))
        self._sortedGlyphNames = currentGlyph.font.unicodeData.sortGlyphNames(
            currentGlyph.layer.keys(), self.alphabetical
        )

        layout = QGridLayout(self)
        self.glyphLabel = QLabel(self.tr("Glyph:"), self)
        self.glyphEdit = QLineEdit(self)
        self.glyphEdit.textChanged.connect(self.updateGlyphList)
        self.glyphEdit.event = self.lineEvent
        self.glyphEdit.keyPressEvent = self.lineKeyPressEvent

        self.beginsWithBox = QRadioButton(self.tr("Begins with"), self)
        self.containsBox = QRadioButton(self.tr("Contains"), self)
        self.beginsWithBox.setChecked(True)
        self.beginsWithBox.toggled.connect(self.updateGlyphList)

        self.glyphList = QListWidget(self)
        self.glyphList.itemDoubleClicked.connect(self.accept)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        line = 0
        layout.addWidget(self.glyphLabel, line, 0, 1, 2)
        layout.addWidget(self.glyphEdit, line, 2, 1, 4)
        line += 1
        layout.addWidget(self.beginsWithBox, line, 0, 1, 3)
        layout.addWidget(self.containsBox, line, 3, 1, 3)
        line += 1
        layout.addWidget(self.glyphList, line, 0, 1, 6)
        line += 1
        layout.addWidget(buttonBox, line, 0, 1, 6)
        self.setLayout(layout)
        self.updateGlyphList()

    def lineEvent(self, event):
        if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
            if self.beginsWithBox.isChecked():
                self.containsBox.toggle()
            else:
                self.beginsWithBox.toggle()
            return True
        else:
            return QLineEdit.event(self.glyphEdit, event)

    def lineKeyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_Up or key == Qt.Key_Down:
            self.glyphList.keyPressEvent(event)
        else:
            QLineEdit.keyPressEvent(self.glyphEdit, event)

    def updateGlyphList(self):
        beginsWith = self.beginsWithBox.isChecked()
        self.glyphList.clear()
        if not self.glyphEdit.isModified():
            self.glyphList.addItems(self._sortedGlyphNames)
        else:
            text = self.glyphEdit.text()
            if beginsWith:
                glyphs = [
                    glyphName
                    for glyphName in self._sortedGlyphNames
                    if glyphName and glyphName.startswith(text)
                ]
            else:
                glyphs = [
                    glyphName
                    for glyphName in self._sortedGlyphNames
                    if glyphName and text in glyphName
                ]
            self.glyphList.addItems(glyphs)
        self.glyphList.setCurrentRow(0)

    @classmethod
    def getNewGlyph(cls, parent, currentGlyph):
        dialog = cls(currentGlyph, parent)
        result = dialog.exec_()
        currentItem = dialog.glyphList.currentItem()
        newGlyph = None
        if currentItem is not None:
            newGlyphName = currentItem.text()
            if newGlyphName in currentGlyph.layer:
                newGlyph = currentGlyph.layer[newGlyphName]
        return (newGlyph, result)
Пример #32
0
class NodeListWidget (QWidget):
    def __init__ (self, parent):
        super().__init__(parent)
        self.search = SearchWidget(self)
        self.search.searched.connect(self.populatelist)
        
        self.nodelist = QListWidget(self)
        self.nodelist.setSortingEnabled(True)
        self.nodelist.setIconSize(QSize(*(FlGlob.mainwindow.style.boldheight,)*2))
        self.nodelist.currentItemChanged.connect(self.selectnode)
        self.nodelist.itemSelectionChanged.connect(self.onselectionchange)
        self.nodelist.itemActivated.connect(self.activatenode)
        self.nodelist.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        remwidget = QToolBar(self)
        remselected = QAction("Remove Selected", self)
        remselected.setIcon(QIcon.fromTheme("edit-delete"))
        remselected.setToolTip("Remove selected")
        remselected.triggered.connect(self.remselected)
        self.remselaction = remselected
        remtrash = QAction("Remove Trash", self)
        remtrash.setIcon(QIcon.fromTheme("edit-clear"))
        remtrash.setToolTip("Clear all trash")
        remtrash.triggered.connect(self.remtrash)
        self.remtrashaction = remtrash
        remwidget.addAction(remselected)
        remwidget.addAction(remtrash)
        
        layout = QVBoxLayout(self)
        layout.addWidget(self.search)
        layout.addWidget(self.nodelist)
        layout.addWidget(remwidget)
        self.view = None
        self.active = False
        self.setEnabled(False)
    
    @pyqtSlot()
    def setview (self):
        self.view = FlGlob.mainwindow.activeview
        if self.view is None:
            self.setEnabled(False)
            self.active = False
        else:
            self.setEnabled(True)
            self.active = True
        self.populatelist()
    
    @pyqtSlot()
    def populatelist (self):
        self.index = dict()
        self.nodelist.clear()
        if not self.active:
            return
        nodecont = self.view.nodecontainer.nodes
        for nodeID, nodeobj in nodecont.items():
            if self.view.hits is not None and nodeID not in self.view.hits:
                continue
            listitem = self.listitem(self.view, nodeobj, nodeID)
            self.nodelist.addItem(listitem)
            self.index[nodeID] = listitem
        self.remtrashaction.setEnabled(bool(self.view.trash))
    
    @pyqtSlot(str)
    def selectbyID (self, nodeID):
        if not self.active:
            return
        if nodeID in self.index:
            self.nodelist.setCurrentItem(self.index[nodeID])
    
    def listitem (self, view, nodeobj, nodeID):
        typename = nodeobj.typename
        if   typename == "root":
            descr = ""
        elif typename == "bank":
            descr = "(%s) %s" % (nodeobj.bankmode, ", ".join(nodeobj.subnodes))
        elif typename == "talk":
            descr = "[%s]" % elidestring(nodeobj.text, 30)
        elif typename == "response":
            descr = "[%s]" % elidestring(nodeobj.text, 30)
        else:
            descr = ""
        
        label = "%s: %s %s" % (nodeID, typename, descr) 
        if nodeID in view.trash:
            trash = True
            icon = QIcon.fromTheme("user-trash")
        else:
            trash = False
            icon = QIcon.fromTheme("text-x-generic")
        item = NodeListItem(icon, label)
        item.setData(item.IDRole, int(nodeID))
        item.setData(item.TrashRole, trash)
        return item
    
    @pyqtSlot(QListWidgetItem, QListWidgetItem)
    def selectnode (self, listitem, olditem):
        if listitem is None:
            return
        window = FlGlob.mainwindow
        view = window.activeview
        nodeID = str(listitem.data(listitem.IDRole))
        window.setselectednode(view, nodeID)
    
    @pyqtSlot()
    def onselectionchange (self):
        selected = self.nodelist.selectedItems()
        seltrash = [item for item in selected if item.data(item.TrashRole)]
        self.remselaction.setEnabled(bool(seltrash))
    
    @pyqtSlot(QListWidgetItem)
    def activatenode (self, listitem):
        window = FlGlob.mainwindow
        view = window.activeview
        nodeID = str(listitem.data(listitem.IDRole))
        window.setactivenode(view, nodeID)
    
    @pyqtSlot()
    def remselected (self):
        selected = self.nodelist.selectedItems()
        seltrash = [item for item in selected if item.data(item.TrashRole)]
        answer = QMessageBox.question(self, "Node removal", 
            "Permanently remove selected trash nodes (%s)?\n\nThis will also clear the undo action list." % len(seltrash))
        if answer == QMessageBox.No:
            return
        self.view.removenodes([str(item.data(item.IDRole)) for item in selected])
        self.remselaction.setEnabled(False)
    
    @pyqtSlot()
    def remtrash (self):
        count = len(self.view.trash)
        answer = QMessageBox.question(self, "Node removal", 
            "Permanently remove all (%s) trash nodes?\n\nThis will also clear the undo action list." % count)
        if answer == QMessageBox.No:
            return
        self.remtrashaction.setEnabled(False)
        self.view.removetrash()
Пример #33
0
class Window(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.mainWidget = QWidget()
        self.mainWidget.setMinimumSize(QtCore.QSize(640, 480))
        self.mainWidget.setWindowTitle("menoTulo")
        self.grid = QVBoxLayout()
        self.ui()

    def inputGrid(self):
        self.inputGrid = QHBoxLayout()
        self.otsikko = QLineEdit(self)
        self.summa = QLineEdit(self)
        self.otsikko.setPlaceholderText("Tulon/menon kuvaus...")
        self.summa.setPlaceholderText("Summa...")
        self.inputGrid.addWidget(self.otsikko)
        self.inputGrid.addWidget(self.summa)
        self.grid.addLayout(self.inputGrid)

    def nappiGrid(self):
        self.nappiGrid = QHBoxLayout()

        self.tuloButton = QPushButton("Lisää tulo", self)
        self.menoButton = QPushButton("Lisää meno", self)

        self.tuloButton.clicked.connect(self.addTulo)
        self.menoButton.clicked.connect(self.addMeno)

        self.nappiGrid.addWidget(self.tuloButton)
        self.nappiGrid.addWidget(self.menoButton)
        self.grid.addLayout(self.nappiGrid)

    def listaGrid(self):
        self.listaGrid = QHBoxLayout()
        self.tuloLista = QListWidget()
        self.menoLista = QListWidget()

        self.tuloLista.itemClicked.connect(self.deleteItem)
        self.menoLista.itemClicked.connect(self.deleteItem)

        self.listaGrid.addWidget(self.tuloLista)
        self.listaGrid.addWidget(self.menoLista)
        self.grid.addLayout(self.listaGrid)

    def totalGrid(self):
        self.totalGrid = QHBoxLayout()

        self.totalSum = 0
        self.totalMenot = 0
        self.totalTulot = 0

        self.tuloLabel = QLabel()
        self.sumLabel = QLabel()
        self.menoLabel = QLabel()
        self.clearButton = QPushButton("TYHJENNÄ KAIKKI", self)
        self.clearButton.clicked.connect(self.clearAll)

        self.totalGrid.addWidget(self.tuloLabel)
        self.totalGrid.addWidget(self.sumLabel)
        self.totalGrid.addWidget(self.menoLabel)
        self.totalGrid.addWidget(self.clearButton)

        self.tuloLabel.setText("TULOT:")
        self.sumLabel.setText("TOTAL:")
        self.menoLabel.setText("MENOT:")

        self.grid.addLayout(self.totalGrid)

    def ui(self):
        self.inputGrid()
        self.nappiGrid()
        self.listaGrid()
        self.totalGrid()
        self.mainWidget.setLayout(self.grid)
        self.mainWidget.show()

    def virhe(self):
        QMessageBox.about(self, "Virhe", "Syötä summaan vain numeroita!")

    def poistoVarmistus(self):
        vastaus = QMessageBox.question(self, "Poista valittu",
                                       "Poistetaanko varmasti?",
                                       QMessageBox.No | QMessageBox.Yes)
        if vastaus == QMessageBox.Yes:
            return True
        return False

    def tyhjennysVarmistus(self):
        vastaus = QMessageBox.question(self, "Tyhjennä kaikki",
                                       "Oletko varma?",
                                       QMessageBox.No | QMessageBox.Yes)
        if vastaus == QMessageBox.Yes:
            return True
        return False

    def clearAll(self):
        if self.tyhjennysVarmistus():
            self.totalSum = 0
            self.totalMenot = 0
            self.totalTulot = 0
            self.tuloLista.clear()
            self.menoLista.clear()
            self.tuloLabel.setText("TULOT:")
            self.sumLabel.setText("TOTAL:")
            self.menoLabel.setText("MENOT:")

    def deleteItem(self):
        if self.sender() == self.tuloLista:
            lista = self.tuloLista
        else:
            lista = self.menoLista

        if not lista.selectedItems():
            return

        if self.poistoVarmistus():
            for item in lista.selectedItems():
                poistoSumma = int(
                    lista.takeItem(lista.row(item)).text().split()[0])
                lista.takeItem(lista.row(item))
                if lista == self.tuloLista:
                    self.totalTulot -= poistoSumma
                else:
                    self.totalMenot -= poistoSumma
                self.updateTotal()

        self.tuloLista.clearSelection()
        self.menoLista.clearSelection()

    def updateTotal(self):
        self.tuloLabel.setText("TULOT: " + str(self.totalTulot))
        self.menoLabel.setText("MENOT: " + str(self.totalMenot))

        self.totalSum = self.totalTulot - self.totalMenot
        self.sumLabel.setText("TOTAL: " + str(self.totalSum))

    def addMeno(self):
        if not self.summa.text().isdigit():
            self.virhe()
            self.summa.clear()
        else:
            infoText = self.summa.text() + " " + self.otsikko.text()
            if infoText != " ":
                self.menoLista.addItem(infoText)
                self.totalSum -= int(self.summa.text())
                self.sumLabel.setText("TOTAL: " + str(self.totalSum))
                self.totalMenot += int(self.summa.text())
                self.menoLabel.setText("MENOT: " + str(self.totalMenot))
                self.summa.clear()
                self.otsikko.clear()
            else:
                pass

    def addTulo(self):
        if not self.summa.text().isdigit():
            self.virhe()
            self.summa.clear()
        else:
            infoText = self.summa.text() + " " + self.otsikko.text()
            if infoText != " ":
                self.tuloLista.addItem(infoText)
                self.totalSum += int(self.summa.text())
                self.sumLabel.setText("TOTAL: " + str(self.totalSum))
                self.totalTulot += int(self.summa.text())
                self.tuloLabel.setText("TULOT: " + str(self.totalTulot))
                self.summa.clear()
                self.otsikko.clear()
            else:
                pass
Пример #34
0
class DebuggerMainWindow(object):
    def __init__(self, comm):
        self.comm = comm
        self.follow_state = True
        self.init_instances()
        self.init_widgets()
        self.init_actions()
        self.window.closeEvent = self.close_handler
        self.window.showMaximized()

    def run(self):
        self.poll_timer = QTimer()
        self.poll_timer.timeout.connect(self.poll_handler)
        self.comm.start_worker()
        self.poll_timer.start(1000)

    def poll_handler(self):
        self.comm.put_job(self.comm.get_agent_track)
        data = self.comm.take_data()
        for location_info, state in data:
            file_name, node_id = location_info
            i = self.get_instance(file_name)

            if i is None:
                text = "%s:%s" % (str(location_info), state)
            else:
                node = i.model.get_node(node_id)
                if node is not None:
                    text = "%s: %s: %s" % (file_name, node.get_display_text(), state)
                else:
                    text = "%s:%s" % (str(location_info), state)
            self.add_to_history_list(location_info, text)
        if self.follow_state:
            self.focus_last()

    def init_widgets(self):
        self.window = loadUi(MAIN_UI_PATH)
        self.mdi = self.window.mdiArea
        self.mdi.setViewMode(QMdiArea.TabbedView)
        self.mdi.setTabsMovable(True)
        self.mdi.setTabsClosable(True)
        self.mdi.setTabShape(QTabWidget.Rounded)
        self.dock_anchor = self.window.dockAnchor
        self.dock_anchor.layout().setAlignment(Qt.AlignTop)

        self.history_list = QListWidget()
        self.history_list.itemSelectionChanged.connect(self.list_item_selected)
        self.add_dock_content(self.history_list)

    def list_item_selected(self):
        citem = self.history_list.currentItem()
        self.focus_on_location(citem.location_info)

    def init_instances(self):
        self.instances = {}

    def remove_instance(self, ins):
        file_name = ins.file_name
        self.instances.pop(file_name)

    def add_instance(self, ins):
        file_name = ins.file_name
        self.instances[file_name] = ins

    def get_instance(self, file_name):
        if file_name in self.instances:
            return self.instances[file_name]
        else:
            full_path = GraphInstanceVM.get_full_path(file_name)
            model = GraphInstanceVM.get_model(full_path)
            if model is None:
                return None
            ins = GraphInstanceVM(model, self, file_name)
            return ins

    def init_actions(self):
        self.window.actionResume.triggered.connect(self.action_resume_handler)
        self.window.actionStop.triggered.connect(self.action_stop_handler)
        self.window.actionFollow.triggered.connect(self.action_follow_handler)
        self.window.actionHold.triggered.connect(self.action_hold_handler)

    def action_resume_handler(self):
        self.clear_list()
        self.comm.put_job(functools.partial(self.comm.track_agent, True))

    def action_stop_handler(self):
        self.comm.put_job(functools.partial(self.comm.track_agent, False))

    def action_follow_handler(self):
        self.follow_state = True

    def action_hold_handler(self):
        self.follow_state = False

    def close_handler(self, ev):
        # disable tracking for some agents
        self.poll_timer.stop()
        self.comm.put_job(self.comm.finish)
        self.comm.shutdown()

    def add_dock_content(self, widget):
        self.clear_dock_contents()
        self.dock_anchor.layout().addWidget(widget)

    def get_dock_contents(self):
        l = self.dock_anchor.layout()
        ret = []
        for i in range(l.count()):
            ret.append(l.itemAt(i).widget())
        return ret

    def clear_dock_contents(self):
        ws = self.get_dock_contents()
        for w in ws:
            w.deleteLater()

    def focus_on_location(self, location):
        file_name, node_id = location
        instance = self.get_instance(file_name)
        if instance is None:
            logger.fatal("can not find src file for %s" % file_name)
            return False
        ret = instance.focus_on(node_id)
        if ret is False:
            logger.fatal("can not find node %s for %s" % (node_id, file_name))
            return False
        return True

    def add_to_history_list(self, location, text):
        item = HistoryListItem(location, text)
        self.history_list.addItem(item)

    def clear_list(self):
        self.history_list.clear()

    def focus_last(self):
        c = self.history_list.count()
        if c > 0:
            item = self.history_list.item(c-1)
            self.history_list.setCurrentItem(item)
            self.focus_on_location(item.location_info)
Пример #35
0
class DropWidget(QWidget):
    """
    Pyqt5 widget to show items in a QListWidget with Checks. It is used in
    PlotSplitter.
    """
    # Signals
    list2drop = pyqtSignal(list, list, bool)

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

        self.init_ui()

    def init_ui(self):
        """Layout and main functionality."""
        # Labels
        drop_label = QLabel("Delete parameter")

        # Lists
        self.drop_list = QListWidget(self)

        # Buttons
        apply_drop_button = QPushButton("Apply")
        apply_drop_button.clicked.connect(self.send_labels)
        hide_drop_button = QPushButton("Hide")
        hide_drop_button.clicked.connect(self.hide)

        # Radio buttons
        self.all_radio = QRadioButton("All", self)
        self.all_radio.setChecked(True)
        self.good_radio = QRadioButton("Use QC Flags = 0 and 1", self)
        self.one_radio = QRadioButton("Remove QC flag: ", self)

        # Check box
        self.drop_nan_check = QCheckBox("Drop NaN", self)
        self.drop_nan_check.setChecked(True)

        # Spin inputs
        self.qc_spin_box = QSpinBox(self)
        self.qc_spin_box.setMinimum(0)
        self.qc_spin_box.setMaximum(9)
        self.qc_spin_box.setValue(0)

        # Layout
        # - Horizontal Layout for one_radio -
        h_one = QHBoxLayout()
        h_one.addWidget(self.one_radio)
        h_one.addWidget(self.qc_spin_box)
        # - General layout -
        v_drop = QVBoxLayout()
        v_drop.addWidget(drop_label)
        v_drop.addWidget(self.drop_list)
        v_drop.addWidget(self.all_radio)
        v_drop.addWidget(self.good_radio)
        v_drop.addLayout(h_one)
        v_drop.addWidget(self.drop_nan_check)
        v_drop.addWidget(apply_drop_button)
        v_drop.addWidget(hide_drop_button)
        self.setLayout(v_drop)

    def add_labels(self, labels):
        """Add items to self.drop_list"""
        # Clear the list
        self.drop_list.clear()
        # Add new items
        self.drop_list.addItems(labels)

        # Configure the items checkable
        for index in range(self.drop_list.count()):
            item = self.drop_list.item(index)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)

    def send_labels(self):
        """
        It returns the list of checked items from self.drop_list. It also send
        the signal list2drop with the list.

        Returns
        -------
            (labels, flag_list): (list of str, list of int)
                (List with checked labels from self.drop_list, List of flags)
        """
        # Look for checked items and create the list
        labels = []
        for index in range(self.drop_list.count()):
            item = self.drop_list.item(index)
            if item.checkState():
                labels.append(item.text())

        # Flag lists
        flag_list = []
        if self.all_radio.isChecked():
            flag_list = [None]
        elif self.good_radio.isChecked():
            flag_list = [2, 3, 4, 5, 6, 7, 8, 9]
        elif self.one_radio.isChecked():
            flag_list = [self.qc_spin_box.value()]
        # Send the signal
        if labels:
            self.list2drop.emit(labels, flag_list,
                                self.drop_nan_check.isChecked())
        return labels, flag_list
Пример #36
0
class PaletteChooser(QDialog):
    def __init__(self, parent, modelwrapper):
        """
        This window will open a palette chooser to let users select a palette from the (global) list of possible
        palettes.

        :param parent: The parent window, should be the current instance of MainWindow.
        :param modelwrapper: The wrapper of the model.
        """

        super().__init__(parent=parent)
        self.setWindowTitle("Choose Palette")

        self.modelwrapper = modelwrapper

        # vertical layout as central panel.
        vlayout = QVBoxLayout()
        self.setLayout(vlayout)
        self.setFixedSize(300, 400)
        # add a list widget to view all the pretty palettes.
        self.list = QListWidget()
        self.list.setSelectionMode(1)
        vlayout.addWidget(self.list)

        options = QWidget()
        opts_layout = QVBoxLayout()
        options.setLayout(opts_layout)
        vlayout.addWidget(options)

        ubox = QWidget()
        ulayout = QHBoxLayout()
        ubox.setLayout(ulayout)
        vlayout.addWidget(ubox)

        ulayout.addWidget(QLabel("upper bound:"))
        self.upperBoundField = QSpinBox()
        self.upperBoundField.setRange(-2147483648, 2147483647)
        self.upperBoundField.setValue(modelwrapper.model.upper_bound)
        self.upperBoundField.setSingleStep(
            (modelwrapper.model.highest - modelwrapper.model.lowest) / 1000)
        ulayout.addWidget(self.upperBoundField)

        lbox = QWidget()
        llayout = QHBoxLayout()
        lbox.setLayout(llayout)
        vlayout.addWidget(lbox)

        llayout.addWidget(QLabel("lower bound:"))
        self.lowerBoundField = QSpinBox()
        self.lowerBoundField.setRange(-2147483648, 2147483647)
        self.lowerBoundField.setValue(modelwrapper.model.lower_bound)
        self.lowerBoundField.setSingleStep(
            (modelwrapper.model.highest - modelwrapper.model.lowest) / 1000)
        llayout.addWidget(self.lowerBoundField)

        # add a button bar at the bottom.
        button_bar = QWidget()
        button_bar_layout = QHBoxLayout()
        button_bar.setLayout(button_bar_layout)
        vlayout.addWidget(button_bar)

        # add a cancel button.
        cancel_button = QPushButton('Cancel')
        cancel_button.clicked.connect(self.close)
        button_bar_layout.addWidget(cancel_button)

        # add import palette button
        import_button = QPushButton('Import')
        import_button.clicked.connect(self.import_palette)
        button_bar_layout.addWidget(import_button)

        # add apply button.
        apply_button = QPushButton('Apply')
        apply_button.clicked.connect(self.apply)
        button_bar_layout.addWidget(apply_button)

        # add a ok button.
        ok_button = QPushButton('OK')
        ok_button.clicked.connect(self.ok)
        button_bar_layout.addWidget(ok_button)

        self.gen_palette_list()

    def gen_palette_list(self):
        self.list.clear()
        for i, palt in enumerate(palettes):
            item = QListWidgetItem(self.list)
            # item.setBackground(QtCore.Qt.red)

            widg = QWidget()
            # widg.setStyleSheet("background-color:blue")
            layo = QHBoxLayout()
            self.list.setItemWidget(item, widg)
            text = QLabel(palt.name)
            text.setSizePolicy(QSizePolicy.Expanding,
                               QSizePolicy.MinimumExpanding)

            grad = QLabel()
            grad.setScaledContents(True)
            grad.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            grad.setPixmap(QPixmap(palt.generate_preview(width=100, height=1)))
            # grad.setStyleSheet("background-color:green")

            layo.addWidget(text)
            layo.addWidget(grad)

            widg.setLayout(layo)
            widg.setSizePolicy(QSizePolicy.Expanding,
                               QSizePolicy.MinimumExpanding)

            item.setSizeHint(widg.sizeHint())
            if self.modelwrapper.get_preference(
                    PreferenceEnum.PALETTE) is palt:
                self.list.setCurrentRow(i)

    def import_palette(self):
        files, _ = QFileDialog.getOpenFileNames(
            None, "Import palette file", "",
            "Palette Files (*.palette);;All Files(*)")
        loaded = []
        for file in files:
            loaded.extend(load_custom_palettes(file))

        self.gen_palette_list()

        for file in loaded:
            if not path.exists(path.join(main.CUSTOM_PALETTE_PATH, path.basename(file))) \
                    or not path.samefile(file, path.join(main.CUSTOM_PALETTE_PATH, path.basename(file))):
                copy(file, main.CUSTOM_PALETTE_PATH)
        self.close()

        self.parent().add_dialog(
            PaletteChooser(self.parent(), self.modelwrapper))

    def ok(self):
        self.apply()
        self.close()

    def apply(self):
        index = self.list.currentRow()
        self.modelwrapper.set_palette(palettes[index])
        self.modelwrapper.set_lower_bound(self.lowerBoundField.value())
        self.modelwrapper.set_upper_bound(self.upperBoundField.value())

    # TODO is this function still necessary?
    def closeEvent(self, event):
        """ Overrides the closing event to execute the on_close callback after closing.
        This is better than overriding close() because this will also execute when the user presses the x button on the top of the window."""
        event.accept()
        self.parent().dialogs.remove(self)
Пример #37
0
class Ahsoka(QWidget):
    def __init__(self):
        super().__init__()
        self.init()
        self.place()
        self.show()

    def init(self):
        self.setWindowTitle('Ahsoka')
        self.setWindowIcon(QIcon(imgPath('icon.png')))
        self.urlLabel = QLabel('Ссылка:')
        self.nameLabel = QLabel('Название:')
        self.urlEdit = QLineEdit()
        self.nameEdit = QLineEdit()
        self.downloadBtn = QPushButton('Скачать')
        self.updateBtn = QPushButton('Обновить')
        self.gamesList = QListWidget()
        self.enginesBox = QGroupBox('Движки')
        self.playBtn = QPushButton('Играть')
        self.delBtn = QPushButton('Удалить')
        self.statusBar = QStatusBar()
        self.connectAll()

    def successMessage(self, message):
        self.statusBar.setStyleSheet('color: green')
        self.statusBar.showMessage(message)

    def errorMessage(self, message):
        self.statusBar.setStyleSheet('color: red')
        self.statusBar.showMessage(message)

    def connectAll(self):
        self.downloadBtn.clicked.connect(self.downloadGame)
        self.updateBtn.clicked.connect(self.setGames)
        self.gamesList.setVerticalScrollBar(QScrollBar())
        self.setEngines()
        self.setGames()
        self.playBtn.clicked.connect(self.play)
        self.delBtn.clicked.connect(self.delGame)
        self.successMessage('Добро пожаловать в лучший лаунчер флешек Ahsoka')

    def place(self):
        self.grid = QGridLayout()
        self.grid.setSpacing(5)
        self.grid.addWidget(self.urlLabel, 0, 0, 1, 1)
        self.grid.addWidget(self.urlEdit, 0, 1, 1, 1)
        self.grid.addWidget(self.nameLabel, 1, 0, 1, 1)
        self.grid.addWidget(self.nameEdit, 1, 1, 1, 1)
        self.grid.addWidget(self.downloadBtn, 0, 2, 1, 1)
        self.grid.addWidget(self.updateBtn, 1, 2, 1, 1)
        self.grid.addWidget(self.gamesList, 2, 0, 1, 2)
        self.grid.addWidget(self.enginesBox, 2, 2, 1, 1)
        self.grid.addWidget(self.playBtn, 3, 0, 1, 2)
        self.grid.addWidget(self.delBtn, 3, 2, 1, 1)
        self.grid.addWidget(self.statusBar, 4, 0, 1, 3)
        self.setLayout(self.grid)

    def setGames(self):
        self.gamesList.clear()
        for game in sorted(listdir('games')):
            self.gamesList.addItem(game[:-4].title())

    def setEngines(self):
        enginesLayout = QVBoxLayout()
        for engine in ['flashplayer']:
            btn = QRadioButton(engine.capitalize())
            if 'flashplayer' in engine:
                btn.setChecked(True)
            enginesLayout.addWidget(btn)
        self.enginesBox.setLayout(enginesLayout)

    def wget(self, *args, **kwargs):
        download(*args, **kwargs)
        self.setGames()
        self.urlEdit.clear()
        self.nameEdit.clear()
        self.successMessage('Загрузка завершена')

    def downloadGame(self):
        try:
            url = swf = self.urlEdit.text().strip()
            name = self.nameEdit.text().strip()
            if not url.endswith('.swf'):
                req = get(url)
                self.statusBar.showMessage(str(req))
                try:
                    html = req.content.decode('utf-8')
                except:
                    html = req.content.decode('cp1251')
                swf = findall(r'\".[^"]+\.swf\"', html)[0][1:-1]
                swf = urljoin(url, swf)
            print(swf)
            self.successMessage('Скачивание...')
            args = swf,
            kwargs = {
                'out': 'games/'
            } if not name else {
                'out': getGamePath(name)
            }
            Thread(target=self.wget, args=args, kwargs=kwargs).start()
        except Exception as Exc:
            print(Exc)
            self.urlEdit.clear()
            self.errorMessage('Попробуйте другую ссылку')

    def delGame(self):
        game = self.gamesList.currentItem()
        if game is None:
            return
        remove(getGamePath(game.text()))
        self.setGames()
        self.successMessage('Игра удалена')

    def play(self):
        game = self.gamesList.currentItem()
        if game is None:
            return
        engine = libPath(
            ('flashplayer' if sys.platform == 'linux' else 'flashplayer.exe'))
        args = f'{engine} \"{getGamePath(game.text())}\"',
        self.statusBar.showMessage('Игра запущена')
        Thread(target=popen, args=args).start()
class NewProjectManager(QDialog):

    def __init__(self, parent=None):
        super(NewProjectManager, self).__init__(parent, Qt.Dialog)
        self.setWindowTitle(translations.TR_NEW_PROJECT)
        self.setMinimumHeight(500)
        vbox = QVBoxLayout(self)
        vbox.addWidget(QLabel(translations.TR_CHOOSE_TEMPLATE))
        vbox.addWidget(QLabel(translations.TR_TAB_PROJECTS))

        hbox = QHBoxLayout()
        self.list_projects = QListWidget()
        self.list_projects.setProperty("wizard", True)
        hbox.addWidget(self.list_projects)

        self.list_templates = QListWidget()
        self.list_templates.setProperty("wizard", True)
        hbox.addWidget(self.list_templates)

        self.text_info = QTextBrowser()
        self.text_info.setProperty("wizard", True)
        hbox.addWidget(self.text_info)

        vbox.addLayout(hbox)

        hbox2 = QHBoxLayout()
        cancel = QPushButton(translations.TR_CANCEL)
        choose = QPushButton(translations.TR_CHOOSE)
        hbox2.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding,
                            QSizePolicy.Fixed))
        hbox2.addWidget(cancel)
        hbox2.addWidget(choose)
        vbox.addLayout(hbox2)

        self.template_registry = IDE.get_service("template_registry")
        categories = self.template_registry.list_project_categories()
        for category in categories:
            self.list_projects.addItem(category)

        cancel.clicked['bool'].connect(self.close)
        choose.clicked['bool'].connect(self._start_wizard)
        self.list_projects.itemSelectionChanged.connect(self._project_selected)
        self.list_templates.itemSelectionChanged.connect(self._template_selected)

    def _project_selected(self):
        self.list_templates.clear()
        item = self.list_projects.currentItem()
        category = item.text()
        for template in self.template_registry.list_templates_for_cateogory(
                category):
            item = QListWidgetItem(template.type_name)
            item.setData(Qt.UserRole, template)
            item = self.list_templates.addItem(item)

    def _template_selected(self):
        item = self.list_templates.currentItem()
        ptype = item.data(Qt.UserRole)
        self.text_info.setText(ptype.description)

    def _start_wizard(self):
        return QMessageBox.critical(self, "Beta Info", "Can not construct this segment!")
        item = self.list_templates.currentItem()
        if item is not None:
            ptype = item.data(Qt.UserRole)
Пример #39
0
class MusicPlayer(QMainWindow):
    """MusicPlayer houses all of elements that directly interact with the main window."""

    def __init__(self, parent=None):
        """Initialize the QMainWindow widget.

        The window title, window icon, and window size are initialized here as well
        as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar,
        QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and
        QVBoxLayout. The connect signals for relavant widgets are also initialized.
        """
        super(MusicPlayer, self).__init__(parent)
        self.setWindowTitle('Mosaic')

        window_icon = utilities.resource_filename('mosaic.images', 'icon.png')
        self.setWindowIcon(QIcon(window_icon))
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

        # Initiates Qt objects to be used by MusicPlayer
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist_location = defaults.Settings().playlist_path
        self.content = QMediaContent()
        self.menu = self.menuBar()
        self.toolbar = QToolBar()
        self.art = QLabel()
        self.pixmap = QPixmap()
        self.slider = QSlider(Qt.Horizontal)
        self.duration_label = QLabel()
        self.playlist_dock = QDockWidget('Playlist', self)
        self.library_dock = QDockWidget('Media Library', self)
        self.playlist_view = QListWidget()
        self.library_view = library.MediaLibraryView()
        self.library_model = library.MediaLibraryModel()
        self.preferences = configuration.PreferencesDialog()
        self.widget = QWidget()
        self.layout = QVBoxLayout(self.widget)
        self.duration = 0
        self.playlist_dock_state = None
        self.library_dock_state = None

        # Sets QWidget() as the central widget of the main window
        self.setCentralWidget(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # Initiates the playlist dock widget and the library dock widget
        self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock)
        self.playlist_dock.setWidget(self.playlist_view)
        self.playlist_dock.setVisible(defaults.Settings().playlist_on_start)
        self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable)

        self.addDockWidget(defaults.Settings().dock_position, self.library_dock)
        self.library_dock.setWidget(self.library_view)
        self.library_dock.setVisible(defaults.Settings().media_library_on_start)
        self.library_dock.setFeatures(QDockWidget.DockWidgetClosable)
        self.tabifyDockWidget(self.playlist_dock, self.library_dock)

        # Sets the range of the playback slider and sets the playback mode as looping
        self.slider.setRange(0, self.player.duration() / 1000)
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        # OSX system menu bar causes conflicts with PyQt5 menu bar
        if sys.platform == 'darwin':
            self.menu.setNativeMenuBar(False)

        # Initiates Settings in the defaults module to give access to settings.toml
        defaults.Settings()

        # Signals that connect to other methods when they're called
        self.player.metaDataChanged.connect(self.display_meta_data)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.song_duration)
        self.player.positionChanged.connect(self.song_position)
        self.player.stateChanged.connect(self.set_state)
        self.playlist_view.itemActivated.connect(self.activate_playlist_item)
        self.library_view.activated.connect(self.open_media_library)
        self.playlist.currentIndexChanged.connect(self.change_index)
        self.playlist.mediaInserted.connect(self.initialize_playlist)
        self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.library_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path)
        self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size)
        self.art.mousePressEvent = self.press_playback

        # Creating the menu controls, media controls, and window size of the music player
        self.menu_controls()
        self.media_controls()
        self.load_saved_playlist()

    def menu_controls(self):
        """Initiate the menu bar and add it to the QMainWindow widget."""
        self.file = self.menu.addMenu('File')
        self.edit = self.menu.addMenu('Edit')
        self.playback = self.menu.addMenu('Playback')
        self.view = self.menu.addMenu('View')
        self.help_ = self.menu.addMenu('Help')

        self.file_menu()
        self.edit_menu()
        self.playback_menu()
        self.view_menu()
        self.help_menu()

    def media_controls(self):
        """Create the bottom toolbar and controls used for media playback."""
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
        self.play_action = QAction(QIcon(play_icon), 'Play', self)
        self.play_action.triggered.connect(self.player.play)

        stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png')
        self.stop_action = QAction(QIcon(stop_icon), 'Stop', self)
        self.stop_action.triggered.connect(self.player.stop)

        previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png')
        self.previous_action = QAction(QIcon(previous_icon), 'Previous', self)
        self.previous_action.triggered.connect(self.previous)

        next_icon = utilities.resource_filename('mosaic.images', 'md_next.png')
        self.next_action = QAction(QIcon(next_icon), 'Next', self)
        self.next_action.triggered.connect(self.playlist.next)

        repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
        self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self)
        self.repeat_action.setShortcut('R')
        self.repeat_action.triggered.connect(self.repeat_song)

        self.toolbar.addAction(self.play_action)
        self.toolbar.addAction(self.stop_action)
        self.toolbar.addAction(self.previous_action)
        self.toolbar.addAction(self.next_action)
        self.toolbar.addAction(self.repeat_action)
        self.toolbar.addWidget(self.slider)
        self.toolbar.addWidget(self.duration_label)

    def file_menu(self):
        """Add a file menu to the menu bar.

        The file menu houses the Open File, Open Multiple Files, Open Playlist,
        Open Directory, and Exit Application menu items.
        """
        self.open_action = QAction('Open File', self)
        self.open_action.setShortcut('O')
        self.open_action.triggered.connect(self.open_file)

        self.open_multiple_files_action = QAction('Open Multiple Files', self)
        self.open_multiple_files_action.setShortcut('M')
        self.open_multiple_files_action.triggered.connect(self.open_multiple_files)

        self.open_playlist_action = QAction('Open Playlist', self)
        self.open_playlist_action.setShortcut('CTRL+P')
        self.open_playlist_action.triggered.connect(self.open_playlist)

        self.open_directory_action = QAction('Open Directory', self)
        self.open_directory_action.setShortcut('D')
        self.open_directory_action.triggered.connect(self.open_directory)

        self.save_playlist_action = QAction('Save Playlist', self)
        self.save_playlist_action.setShortcut('CTRL+S')
        self.save_playlist_action.triggered.connect(self.save_playlist)

        self.exit_action = QAction('Quit', self)
        self.exit_action.setShortcut('CTRL+Q')
        self.exit_action.triggered.connect(self.closeEvent)

        self.file.addAction(self.open_action)
        self.file.addAction(self.open_multiple_files_action)
        self.file.addAction(self.open_playlist_action)
        self.file.addAction(self.open_directory_action)
        self.file.addSeparator()
        self.file.addAction(self.save_playlist_action)
        self.file.addSeparator()
        self.file.addAction(self.exit_action)

    def edit_menu(self):
        """Add an edit menu to the menu bar.

        The edit menu houses the preferences item that opens a preferences dialog
        that allows the user to customize features of the music player.
        """
        self.preferences_action = QAction('Preferences', self)
        self.preferences_action.setShortcut('CTRL+SHIFT+P')
        self.preferences_action.triggered.connect(lambda: self.preferences.exec_())

        self.edit.addAction(self.preferences_action)

    def playback_menu(self):
        """Add a playback menu to the menu bar.

        The playback menu houses
        """
        self.play_playback_action = QAction('Play', self)
        self.play_playback_action.setShortcut('P')
        self.play_playback_action.triggered.connect(self.player.play)

        self.stop_playback_action = QAction('Stop', self)
        self.stop_playback_action.setShortcut('S')
        self.stop_playback_action.triggered.connect(self.player.stop)

        self.previous_playback_action = QAction('Previous', self)
        self.previous_playback_action.setShortcut('B')
        self.previous_playback_action.triggered.connect(self.previous)

        self.next_playback_action = QAction('Next', self)
        self.next_playback_action.setShortcut('N')
        self.next_playback_action.triggered.connect(self.playlist.next)

        self.playback.addAction(self.play_playback_action)
        self.playback.addAction(self.stop_playback_action)
        self.playback.addAction(self.previous_playback_action)
        self.playback.addAction(self.next_playback_action)

    def view_menu(self):
        """Add a view menu to the menu bar.

        The view menu houses the Playlist, Media Library, Minimalist View, and Media
        Information menu items. The Playlist item toggles the playlist dock into and
        out of view. The Media Library items toggles the media library dock into and
        out of view. The Minimalist View item resizes the window and shows only the
        menu bar and player controls. The Media Information item opens a dialog that
        shows information relevant to the currently playing song.
        """
        self.dock_action = self.playlist_dock.toggleViewAction()
        self.dock_action.setShortcut('CTRL+ALT+P')

        self.library_dock_action = self.library_dock.toggleViewAction()
        self.library_dock_action.setShortcut('CTRL+ALT+L')

        self.minimalist_view_action = QAction('Minimalist View', self)
        self.minimalist_view_action.setShortcut('CTRL+ALT+M')
        self.minimalist_view_action.setCheckable(True)
        self.minimalist_view_action.triggered.connect(self.minimalist_view)

        self.view_media_info_action = QAction('Media Information', self)
        self.view_media_info_action.setShortcut('CTRL+SHIFT+M')
        self.view_media_info_action.triggered.connect(self.media_information_dialog)

        self.view.addAction(self.dock_action)
        self.view.addAction(self.library_dock_action)
        self.view.addSeparator()
        self.view.addAction(self.minimalist_view_action)
        self.view.addSeparator()
        self.view.addAction(self.view_media_info_action)

    def help_menu(self):
        """Add a help menu to the menu bar.

        The help menu houses the about dialog that shows the user information
        related to the application.
        """
        self.about_action = QAction('About', self)
        self.about_action.setShortcut('H')
        self.about_action.triggered.connect(lambda: about.AboutDialog().exec_())

        self.help_.addAction(self.about_action)

    def open_file(self):
        """Open the selected file and add it to a new playlist."""
        filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            file_info = QFileInfo(filename).fileName()
            playlist_item = QListWidgetItem(file_info)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename)))
            self.player.setPlaylist(self.playlist)
            playlist_item.setToolTip(file_info)
            self.playlist_view.addItem(playlist_item)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_multiple_files(self):
        """Open the selected files and add them to a new playlist."""
        filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            self.playlist.clear()
            self.playlist_view.clear()
            for file in natsort.natsorted(filenames, alg=natsort.ns.PATH):
                file_info = QFileInfo(file).fileName()
                playlist_item = QListWidgetItem(file_info)
                self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                self.player.setPlaylist(self.playlist)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)
                self.playlist_view.setCurrentRow(0)
                self.player.play()

    def open_playlist(self):
        """Load an M3U or PLS file into a new playlist."""
        playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly)

        if success:
            playlist = QUrl.fromLocalFile(playlist)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def save_playlist(self):
        """Save the media in the playlist dock as a new M3U playlist."""
        playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '')
        if success:
            saved_playlist = "{}.m3u" .format(playlist)
            self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u")

    def load_saved_playlist(self):
        """Load the saved playlist if user setting permits."""
        saved_playlist = "{}/.m3u" .format(self.playlist_location)
        if os.path.exists(saved_playlist):
            playlist = QUrl().fromLocalFile(saved_playlist)
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)

    def open_directory(self):
        """Open the selected directory and add the files within to an empty playlist."""
        directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly)

        if directory:
            self.playlist.clear()
            self.playlist_view.clear()
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

            self.player.setPlaylist(self.playlist)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_media_library(self, index):
        """Open a directory or file from the media library into an empty playlist."""
        self.playlist.clear()
        self.playlist_view.clear()

        if self.library_model.fileName(index).endswith(('mp3', 'flac')):
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index))))
            self.playlist_view.addItem(self.library_model.fileName(index))

        elif self.library_model.isDir(index):
            directory = self.library_model.filePath(index)
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

        self.player.setPlaylist(self.playlist)
        self.player.play()

    def display_meta_data(self):
        """Display the current song's metadata in the main window.

        If the current song contains metadata, its cover art is extracted and shown in
        the main window while the track number, artist, album, and track title are shown
        in the window title.
        """
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
            (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path)

            try:
                self.pixmap.loadFromData(artwork)
            except TypeError:
                self.pixmap = QPixmap(artwork)

            meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title)

            self.setWindowTitle(meta_data)
            self.art.setScaledContents(True)
            self.art.setPixmap(self.pixmap)
            self.layout.addWidget(self.art)

    def initialize_playlist(self, start):
        """Display playlist and reset playback mode when media inserted into playlist."""
        if start == 0:
            if self.library_dock.isVisible():
                self.playlist_dock.setVisible(True)
                self.playlist_dock.show()
                self.playlist_dock.raise_()

            if self.playlist.playbackMode() != QMediaPlaylist.Sequential:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
                self.repeat_action.setIcon(QIcon(repeat_icon))

    def press_playback(self, event):
        """Change the playback of the player on cover art mouse event.

        When the cover art is clicked, the player will play the media if the player is
        either paused or stopped. If the media is playing, the media is set
        to pause.
        """
        if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked():
            if (self.player.state() == QMediaPlayer.StoppedState or
                    self.player.state() == QMediaPlayer.PausedState):
                self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()

    def seek(self, seconds):
        """Set the position of the song to the position dragged to by the user."""
        self.player.setPosition(seconds * 1000)

    def song_duration(self, duration):
        """Set the slider to the duration of the currently played media."""
        duration /= 1000
        self.duration = duration
        self.slider.setMaximum(duration)

    def song_position(self, progress):
        """Move the horizontal slider in sync with the duration of the song.

        The progress is relayed to update_duration() in order
        to display the time label next to the slider.
        """
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.update_duration(progress)

    def update_duration(self, current_duration):
        """Calculate the time played and the length of the song.

        Both of these times are sent to duration_label() in order to display the
        times on the toolbar.
        """
        duration = self.duration

        if current_duration or duration:
            time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60,
                                (current_duration % 60), (current_duration * 1000) % 1000)
            song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60),
                                (duration * 1000) % 1000)

            if duration > 3600:
                time_format = "hh:mm:ss"
            else:
                time_format = "mm:ss"

            time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format))

        else:
            time_display = ""

        self.duration_label.setText(time_display)

    def set_state(self, state):
        """Change the icon in the toolbar in relation to the state of the player.

        The play icon changes to the pause icon when a song is playing and
        the pause icon changes back to the play icon when either paused or
        stopped.
        """
        if self.player.state() == QMediaPlayer.PlayingState:
            pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png')
            self.play_action.setIcon(QIcon(pause_icon))
            self.play_action.triggered.connect(self.player.pause)

        elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState):
            self.play_action.triggered.connect(self.player.play)
            play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
            self.play_action.setIcon(QIcon(play_icon))

    def previous(self):
        """Move to the previous song in the playlist.

        Moves to the previous song in the playlist if the current song is less
        than five seconds in. Otherwise, restarts the current song.
        """
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def repeat_song(self):
        """Set the current media to repeat and change the repeat icon accordingly.

        There are four playback modes: repeat none, repeat all, repeat once, and shuffle.
        Clicking the repeat button cycles through each playback mode.
        """
        if self.playlist.playbackMode() == QMediaPlaylist.Sequential:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Loop:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Random:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

    def activate_playlist_item(self, item):
        """Set the active media to the playlist item dobule-clicked on by the user."""
        current_index = self.playlist_view.row(item)
        if self.playlist.currentIndex() != current_index:
            self.playlist.setCurrentIndex(current_index)

        if self.player.state() != QMediaPlayer.PlayingState:
            self.player.play()

    def change_index(self, row):
        """Highlight the row in the playlist of the active media."""
        self.playlist_view.setCurrentRow(row)

    def minimalist_view(self):
        """Resize the window to only show the menu bar and audio controls."""
        if self.minimalist_view_action.isChecked():

            if self.playlist_dock.isVisible():
                self.playlist_dock_state = True
            if self.library_dock.isVisible():
                self.library_dock_state = True

            self.library_dock.close()
            self.playlist_dock.close()

            QTimer.singleShot(10, lambda: self.resize(500, 0))

        else:
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

            if self.library_dock_state:
                self.library_dock.setVisible(True)

            if self.playlist_dock_state:
                self.playlist_dock.setVisible(True)

    def dock_visiblity_change(self, visible):
        """Change the size of the main window when the docks are toggled."""
        if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6,
                        self.height())

        elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif (not visible and not self.playlist_dock.isVisible() and not
                self.library_dock.isVisible()):
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def media_information_dialog(self):
        """Show a dialog of the current song's metadata."""
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
        else:
            file_path = None
        dialog = information.InformationDialog(file_path)
        dialog.exec_()

    def change_window_size(self):
        """Change the window size of the music player."""
        self.playlist_dock.close()
        self.library_dock.close()
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def change_media_library_path(self, path):
        """Change the media library path to the new path selected in the preferences dialog."""
        self.library_model.setRootPath(path)
        self.library_view.setModel(self.library_model)
        self.library_view.setRootIndex(self.library_model.index(path))

    def closeEvent(self, event):
        """Override the PyQt close event in order to handle save playlist on close."""
        playlist = "{}/.m3u" .format(self.playlist_location)
        if defaults.Settings().save_playlist_on_close:
            self.playlist.save(QUrl().fromLocalFile(playlist), "m3u")
        else:
            if os.path.exists(playlist):
                os.remove(playlist)
        QApplication.quit()
Пример #40
0
class mainWindow(QTabWidget):
    sendMessage = pyqtSignal(list, name='sendMessage')
    selectFriend = pyqtSignal(list, name='selectFriend')
    selectAutoGroup = pyqtSignal(list, name='selectAutoGroup')
    imgHeadRequest = pyqtSignal(str, name='imgHeadRequest')
    friendAutoReply = pyqtSignal(int, name='friendAutoReply')  # 朋友自动回复

    chatroom_num = 0  # 群个数
    selectGroupAutoReply = []  # 自动回复的群
    '''
    通讯录信息
    | NickName ,Sex,Province,City,signature,FromUserName|
    '''
    AllFriendsInfo = {}

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

        self.focusID = 0
        #        self.setStyle('qrc/black.qss')
        self.createActions()
        self.createTrayIcon()
        self.init()

    def setStyle(self, _qssPath):
        with open(_qssPath, encoding='UTF-8') as file:
            str = file.read()
            qss = ''.join(str)
            self.setStyleSheet(qss)

    def init(self):
        self.tabChat = QWidget()
        self.tabContact = QWidget()
        self.tabSet = QWidget()

        self.addTab(self.tabChat, '微信')
        self.addTab(self.tabContact, '通讯录')
        self.addTab(self.tabSet, '设置')

        self.tabChatInit()
        self.setInit()
        self.contactInit()
        # self.leftLayout = QVBoxLayout()
        # self.rightLayout = QVBoxLayout()
        # mainLayout = QGridLayout()
        #
        # self.contact = QListWidget()
        # self.leftLayout.addWidget(self.contact)
        #
        # self.chatroom = QLineEdit()
        # self.chatroom.setText('This is ChatRoom')
        # self.chatlog = QLabel()
        # self.chatlog.setText('This is ChatLog')
        #
        # self.rightLayout.addWidget(self.chatlog)
        # self.rightLayout.addWidget(self.chatroom)
        #
        # mainLayout.addLayout(self.leftLayout, 0, 0, 1, 1)
        # mainLayout.addLayout(self.rightLayout, 0, 1, 1, 3)
        #
        # self.setLayout(mainLayout)
        self.setWindowTitle(self.tr('Wechat_alpha'))

    def addChatFriend(self, _NickName, _RemarkName):

        item = QListWidgetItem()
        str = _NickName
        if _RemarkName is not '':
            str += '[' + _RemarkName + ']'

        item.setText(str)

        self.listChatting.addItem(item)

    # 通讯录写入名单
    def fillContact(self, _fullContact):

        # self.AllFriendsInfo = _fullContact
        for each in _fullContact:
            item = QListWidgetItem()
            str = each['RemarkName']
            if str is '':
                str = each['NickName']
            item.setText(str)
            self.contactList.addItem(item)
            # | NickName, Sex, Province, City, signature, FromUserName |
            self.AllFriendsInfo[str] = [
                each['NickName'], each['Sex'], each['Province'], each['City'],
                each['Signature'], each['UserName']
            ]

    # 群自动回复----获得群名
    def setChatroomFill(self, _chatroom):

        self.chatroom_num = 0
        for each in _chatroom:
            self.chatroom_num += 1
            # self.chatroomInfo[each['NickName']] = each['UserName']
            item = QListWidgetItem()
            str = each['NickName']
            item.setText(str)
            self.allGroupList.addItem(item)
        # print(self.chatroomInfo)

    def contactInit(self):

        size = self.size()

        self.contactList = QListWidget()
        self.contactList.setFixedSize(size.width() / 3, size.height())
        self.contactList.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.contactList.itemClicked.connect(self.contactListClick)

        infoWidget = QWidget()
        infoWidget.setFixedSize(size.width() * 2 / 3, size.height())

        topLayout = QGridLayout()
        midLayout = QVBoxLayout()
        bottomLayout = QHBoxLayout()

        # top
        self.headLabel = QLabel()  # 头像
        self.headLabel.setFixedSize(150, 150)
        self.headLabel.setScaledContents(True)

        self.signatureLabel = QLabel()  # 签名
        self.signatureLabel.setAlignment(QtCore.Qt.AlignVCenter)
        self.nickNameLabel = QLabel()  # 微信名
        self.nickNameLabel.setAlignment(QtCore.Qt.AlignVCenter)

        topLayout.addWidget(self.nickNameLabel, 1, 0, 1, 3)
        topLayout.addWidget(self.signatureLabel, 2, 0, 1, 3)
        topLayout.addWidget(self.headLabel, 0, 1, 1, 1)

        # mid
        self.remarkNameLabel = QLabel()  # 备注
        self.cityLabel = QLabel()  # 城市

        midLayout.addWidget(self.remarkNameLabel)
        midLayout.addWidget(self.cityLabel)

        # bottom
        self.sendMsgBtn = QPushButton('发消息')

        bottomLayout.addWidget(self.sendMsgBtn)

        layout = QGridLayout()

        infoLayout = QVBoxLayout()
        infoLayout.addLayout(topLayout)
        infoLayout.addLayout(midLayout)
        infoLayout.addLayout(bottomLayout)
        infoLayout.addSpacing(10)

        infoWidget.setLayout(infoLayout)
        layout.addWidget(self.contactList, 0, 0, 1, 1)
        layout.addWidget(infoWidget, 0, 1, 1, 2)

        self.tabContact.setLayout(layout)

    def setInit(self):

        setTab = QTabWidget(self.tabSet)
        setTab.setTabPosition(QTabWidget.West)  # 方向

        size = self.size()

        #############################自动回复################################
        btnAutoSet = QPushButton('应用')
        btnAutoCancel = QPushButton('取消')
        btnAutoCancel.clicked.connect(self.clearSelectList)
        btnAutoSet.clicked.connect(self.setSelectList)

        btnLayout = QHBoxLayout()
        btnLayout.addWidget(btnAutoSet)
        btnLayout.addSpacing(5)
        btnLayout.addWidget(btnAutoCancel)

        self.allGroupList = QListWidget()
        self.selectGroupList = QListWidget()  # 选定自动回复的

        self.allGroupList.setFixedSize(size.width() * 3 / 7,
                                       size.height() * 2 / 3)
        self.selectGroupList.setFixedSize(size.width() * 3 / 7,
                                          size.height() * 2 / 3)

        self.allGroupList.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.selectGroupList.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)

        self.allGroupList.itemDoubleClicked.connect(self.aGroupDoubleClick)
        self.selectGroupList.itemDoubleClicked.connect(self.sGroupDoubleClick)

        self.setAutoLayout = QGridLayout()
        self.autoReplyFriend = QCheckBox('自动回复')
        self.autoReplyFriend.stateChanged.connect(self.setFriendAutoReply)

        self.setAutoLayout.setSpacing(10)

        self.setAutoLayout.addWidget(self.autoReplyFriend, 0, 0, 1, 1)
        self.setAutoLayout.addWidget(self.allGroupList, 1, 0, 10, 1)
        self.setAutoLayout.addWidget(self.selectGroupList, 1, 1, 10, 1)
        self.setAutoLayout.addLayout(btnLayout, 12, 1, 1, 1)

        # for each in self.ChatroomCheckBoxList:
        #     self.setAutoLayout.addWidget(each)
        tabAuto = QWidget()
        tabAuto.setLayout(self.setAutoLayout)
        #####################################################################
        # 其他
        self.showLabel = QLabel()
        self.showLabel.setScaledContents(True)
        self.showLabel.setFixedSize(size.width() * 2 / 3, size.width() * 2 / 3)
        sexDisttibutionBtn = QPushButton('性别分布')
        wordCouldBtn = QPushButton('签名词图')

        sexDisttibutionBtn.clicked.connect(self.calSex)
        wordCouldBtn.clicked.connect(self.generateWordCloud)

        layout = QGridLayout()

        layout.addWidget(self.showLabel, 0, 0, 2, 2)
        layout.addWidget(sexDisttibutionBtn, 2, 0, 1, 1)
        layout.addWidget(wordCouldBtn, 2, 1, 1, 1)
        tabFun = QWidget()
        tabFun.setLayout(layout)
        #####################################################################
        setTab.addTab(tabAuto, '自动回复')
        setTab.addTab(tabFun, '特色功能')
        # setTab.addTab('其他')

    def tabChatInit(self):

        size = self.size()

        layout = QGridLayout()
        self.listChatting = QListWidget()
        self.listChatting.setFixedSize(size.width() / 3, size.height())

        self.chatLog = QTextBrowser()
        self.chatLog.document().setMaximumBlockCount(1000)  # 限制1000行
        self.chatLog.setFixedSize(size.width() * 2 / 3, size.height() * 2 / 3)

        self.textInput = QTextEdit()
        self.textInput.setFixedSize(size.width() * 2 / 3, size.height() / 4)

        self.btnSend = QPushButton()
        self.btnSend.setText('发送')

        # 显示正在聊天的朋友
        self.chattingFri = QLabel('当前聊天朋友:_____')

        self.btnSend.clicked.connect(self.sendMsg)
        self.listChatting.itemClicked.connect(self.listClick)

        self.chatLog.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.chatLog.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        layout.addWidget(self.listChatting, 0, 0, 6, 1)
        layout.addWidget(self.chatLog, 0, 1, 3, 3)
        layout.addWidget(self.textInput, 3, 1, 2, 3)
        layout.addWidget(self.chattingFri, 5, 1, 1, 1)
        layout.addWidget(self.btnSend, 5, 3, 1, 1)

        self.tabChat.setLayout(layout)

    def showChatLog(self, _Msg):

        # count = -1
        #         # for count, line in enumerate(open(thefilepath, 'rU')):
        #         #     pass
        #         # count += 1
        msg_time = time.strftime("%Y-%m-%d %H:%M:%S",
                                 time.localtime(_Msg['time']))
        content = _Msg['content']

        if _Msg['fromusr'] == _Msg['selfusr']:
            self.chatLog.append(msg_time + '\n' + '我' + ':' + content + '\n')
        else:
            fromFriend = _Msg['remarkname']
            self.chatLog.append(msg_time + '\n' + fromFriend + ':' + content +
                                '\n')

    def showSendChatLog(self, _Msg):
        msg_time = time.strftime("%Y-%m-%d %H:%M:%S",
                                 time.localtime(int(time.time())))
        content = _Msg[0]
        self.chatLog.append(msg_time + '\n' + '我' + ':' + content + '\n')

    @pyqtSlot()
    def sendMsg(self):

        sMsg = self.textInput.toPlainText()
        print("::", sMsg)
        if sMsg != '':
            self.textInput.clear()
            self.sendMessage.emit([sMsg])

    @pyqtSlot(QListWidgetItem)
    def listClick(self, item):
        self.selectFriend.emit([item.text()])
        print('好友:', item.text())

    @pyqtSlot(QListWidgetItem)
    def contactListClick(self, item):
        global curTmpImg
        # | NickName, Sex, Province, City, signature, FromUserName |
        cur = self.AllFriendsInfo[item.text()]
        self.imgHeadRequest.emit(cur[5])

        if curTmpImg:
            png = QtGui.QPixmap()
            png.loadFromData(curTmpImg)
            # png.scaled((50,50))
            self.headLabel.setPixmap(png)
            curTmpImg = None

        self.signatureLabel.setText('签名      ' + ''.join(cur[4]))  # 签名
        str = ''.join(cur[0])
        if cur[1] == 1:
            str += ' ♂'
        else:
            str += '  ♀'
        self.nickNameLabel.setText('微信      ' + str)  # 微信名
        self.remarkNameLabel.setText('备注        ' + item.text())  # 备注
        self.cityLabel.setText('地区      ' +
                               ''.join(cur[2] + ' ' + cur[3]))  # 城市

    # add to select list
    @pyqtSlot(QListWidgetItem)
    def aGroupDoubleClick(self, item):
        select = item.text()
        item = QListWidgetItem()
        item.setText(select)
        self.selectGroupList.addItem(item)
        self.selectGroupAutoReply.append(select)

    # remove select item from list
    @pyqtSlot(QListWidgetItem)
    def sGroupDoubleClick(self, item):

        select = item.text()
        self.selectGroupList.removeItemWidget(
            self.selectGroupList.takeItem(self.selectGroupList.row(item)))
        self.selectGroupAutoReply.remove(select)

    @pyqtSlot(int)
    def setFriendAutoReply(self, _state):
        self.friendAutoReply.emit(_state)

    # 清空选定
    def clearSelectList(self):
        self.selectGroupList.clear()
        self.selectGroupAutoReply.clear()

    # 应用群自动回复
    def setSelectList(self):
        self.selectAutoGroup.emit(self.selectGroupAutoReply)

    # 获取头像
    def postUserHead(self, _img):
        global curTmpImg
        curTmpImg = _img
        # print(_img)

    # 更改当前聊天朋友名字显示
    def changeChattingFri(self, _str):
        self.chattingFri.setText('当前发送:' + _str[0])

    #  计算性别
    def calSex(self):

        # 设置全局字体
        plt.rcParams['font.sans-serif'] = ['SimHei']
        # 解决‘-’表现为方块的问题
        plt.rcParams['axes.unicode_minus'] = False

        female = 0
        total = len(self.AllFriendsInfo)
        for each in self.AllFriendsInfo.values():

            if each[1] is 2:
                female += 1
        male = total - female

        data = {'男性(人)': (male, '#7199cf'), '女性(人)': (female, '#ffff10')}

        # 设置绘图对象的大小
        fig = plt.figure(figsize=(8, 8))

        sex = data.keys()
        values = [x[0] for x in data.values()]
        colors = [x[1] for x in data.values()]

        ax1 = fig.add_subplot(111)
        ax1.set_title('性别比例')

        labels = [
            '{}:{}'.format(city, value) for city, value in zip(sex, values)
        ]

        # 设置饼图的凸出显示
        explode = [0, 0.1]

        # 画饼状图, 并且指定标签和对应的颜色
        # 指定阴影效果
        ax1.pie(values,
                labels=labels,
                colors=colors,
                explode=explode,
                shadow=True)

        pngPath = 'cache/_sd/sd.jpg'
        plt.savefig(pngPath)
        # plt.show()
        if os.path.exists(pngPath):
            png = QtGui.QPixmap(pngPath)
            self.showLabel.setPixmap(png)

    # 生成词云
    def generateWordCloud(self):

        signature = [each[4] for each in self.AllFriendsInfo.values()]

        text = ','.join(signature)
        pattern = re.compile('<span.*?</span>')  # 匹配表情
        text = re.sub(repl='', string=text, pattern=pattern)  # 删除表情

        coloring = np.array(Image.open("qrc/back.jpg"))
        my_wordcloud = wordcloud.WordCloud(
            background_color="white",
            max_words=2000,
            mask=coloring,
            max_font_size=60,
            random_state=42,
            scale=2,
            font_path="qrc/FZSTK.ttf"
        ).generate(
            text
        )  # 生成词云。font_path="C:\Windows\Fonts\msyhl.ttc"指定字体,有些字不能解析中文,这种情况下会出现乱码。

        file_name_p = 'cache/word/wc.jpg'
        my_wordcloud.to_file(file_name_p)  # 保存图片

        if os.path.exists(file_name_p):
            png = QtGui.QPixmap(file_name_p)
            self.showLabel.setPixmap(png)

    def createTrayIcon(self):
        '''
        创建托盘图标,可以让程序最小化到windows托盘中运行
        :return:
        '''
        self.trayIconMenu = QMenu(self)
        self.trayIconMenu.addAction(self.restoreAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)
        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(QIcon('qrc/icon.png'))
        self.setWindowIcon(QIcon('qrc/icon.png'))
        self.trayIcon.show()

    def createActions(self):
        '''
        为托盘图标添加功能
        :return:
        '''
        self.restoreAction = QAction("来喽", self, triggered=self.showNormal)
        self.quitAction = QAction("告辞",
                                  self,
                                  triggered=QApplication.instance().quit)

    def iconActivated(self, reason):
        '''
        激活托盘功能
        :param reason:
        :return:
        '''
        if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
            self.showNormal()

    # 弹窗提醒
    def msgWarning(self, _message, _type):

        if _type == 0:
            QMessageBox.information(self, "红包提醒", _message, QMessageBox.Yes)
        else:
            QMessageBox.information(self, "撤回提醒", _message, QMessageBox.Yes)
Пример #41
0
class PeersDialog(QDialog):

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

        self.peers = peers

        self.setWindowModality(Qt.ApplicationModal)
        self.setMaximumSize(500, 200)
        self.setMinimumSize(500, 200)
        self.resize(500, 200)

        self.setLayout(QHBoxLayout())

        self.listWidget = QListWidget(self)
        self.listWidget.setAlternatingRowColors(True)
        self.layout().addWidget(self.listWidget)

        for peer in self.peers:
            self.listWidget.addItem(peer['uri'])

        self.buttonsLayout = QVBoxLayout()
        self.layout().addLayout(self.buttonsLayout)

        self.discoverPeersButton = QPushButton(self)
        self.addPeerButton = QPushButton(self)
        self.removePeerButton = QPushButton(self)
        self.removeAllButton = QPushButton(self)

        self.discoverPeersButton.clicked.connect(self.discover_peers)
        self.addPeerButton.clicked.connect(self.add_peer)
        self.removePeerButton.clicked.connect(self.remove_peer)
        self.removeAllButton.clicked.connect(self.remove_all)

        self.buttonsLayout.addWidget(self.discoverPeersButton)
        self.buttonsLayout.addWidget(self.addPeerButton)
        self.buttonsLayout.addWidget(self.removePeerButton)
        self.buttonsLayout.addWidget(self.removeAllButton)
        self.buttonsLayout.addSpacing(70)

        self.dialogButton = QDialogButtonBox(self)
        self.dialogButton.setStandardButtons(self.dialogButton.Ok)
        self.dialogButton.accepted.connect(self.accept)
        self.buttonsLayout.addWidget(self.dialogButton)

        self.layout().setStretch(0, 2)
        self.layout().setStretch(1, 1)

        self.retranslateUi()

    def retranslateUi(self):
        self.setWindowTitle("Manage connected peers")
        self.discoverPeersButton.setText('Discover peers')
        self.addPeerButton.setText("Manually add a peer")
        self.removePeerButton.setText("Remove selected peer")
        self.removeAllButton.setText("Remove all peers")

    def add_peer(self):
        ip, ok = QInputDialog.getText(None, 'Address', 'Peer IP')
        if ok:
            self._add_peer(ip)

    def _add_peer(self, ip):
        port = config['Remote']['BindPort']
        uri = compose_uri(ip, port)

        for peer in self.peers:
            if peer['uri'] == uri:
                QMessageBox.critical(None, 'Error', 'Already connected')
                return

        try:
            peer = {'proxy': RemoteController.connect_to(uri), 'uri': uri}
            self.peers.append(peer)
            self.listWidget.addItem(peer['uri'])
        except Exception as e:
            QMessageBox.critical(None, 'Error', str(e))

    def discover_peers(self):
        dialog = PeersDiscoveryDialog()
        if dialog.exec_() == dialog.Accepted:
            for peer in dialog.get_peers():
                self._add_peer(peer)

    def remove_peer(self):
        if len(self.listWidget.selectedIndexes()) != 0:
            self.peers.pop(self.current_index())
            self.listWidget.takeItem(self.current_index())

    def remove_all(self):
        self.peers.clear()
        self.listWidget.clear()

    def current_index(self):
        return self.listWidget.selectedIndexes()[0].row()
Пример #42
0
class FoldersManager(QWidget):
    def __init__(self, main_parent=None):
        super(FoldersManager, self).__init__()
        self.mainwindow = main_parent

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setGeometry(50, 50, 350, 250)
        self.setMinimumSize(450, 350)
        self.setMaximumSize(450, 350)
        self.setFont(QFont("Consolas", 10))
        self.setWindowTitle("Folders Manager")
        self.setWindowIcon(QIcon(files.Images.HQPLAYER_LOGO))

        self.explanation_label = QLabel(self)
        self.explanation_label.setGeometry(14, 20, 250, 16)
        self.explanation_label.setToolTip("Music folders used for the playlist.")
        self.explanation_label.setText("Music folders used for the playlist.")

        self.add_button = QPushButton(self)
        self.add_button.setGeometry(405, 60, 25, 25)
        self.add_button.setToolTip("Add folder")
        self.add_button.setIcon(QIcon(files.Images.ADD))
        self.add_button.setIconSize(QSize(25, 25))
        self.add_button.setFocusPolicy(Qt.ClickFocus)

        self.remove_button = QPushButton(self)
        self.remove_button.setGeometry(405, 90, 25, 25)
        self.remove_button.setToolTip("Remove folder")
        self.remove_button.setIcon(QIcon(files.Images.REMOVE))
        self.remove_button.setIconSize(QSize(25, 25))
        self.remove_button.setFocusPolicy(Qt.ClickFocus)

        self.folder_list = QListWidget(self)
        self.folder_list.setGeometry(10, 40, 373, 300)
        self.folder_list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.folder_list.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.folder_list.setEditTriggers(QListWidget.SelectedClicked)
        self.folder_list.setDefaultDropAction(Qt.IgnoreAction)

        self.add_button.released.connect(self.ab_released)
        self.add_button.clicked.connect(self.ab_clicked)
        self.remove_button.released.connect(self.rm_released)
        self.remove_button.clicked.connect(self.rm_clicked)

    def remove_sel(self):
        list_items = self.folder_list.selectedItems()
        if not list_items:
            return
        for item in list_items:
            self.folder_list.takeItem(self.folder_list.row(item))

    def refresh_list(self):
        self.folder_list.clear()
        if self.mainwindow.options.user_music_folders is not None:
            for folder in self.mainwindow.options.user_music_folders:
                self.folder_list.addItem(folder)
        self.folder_list.sortItems()

    def get_selected_item(self):
        return (self.folder_list.selectedItems()[0]).text()

    def ab_released(self):
        self.add_button.clearFocus()

    def rm_released(self):
        self.remove_button.clearFocus()

    def ab_clicked(self):
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.DirectoryOnly)
        file_dialog.setDirectory(self.mainwindow.options.get_default_last_folder_opened())
        file_dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        file_view = file_dialog.findChild(QListView, 'listView')

        # to make it possible to select multiple directories:
        if file_view:
            file_view.setSelectionMode(QAbstractItemView.MultiSelection)
        f_tree_view = file_dialog.findChild(QTreeView)
        if f_tree_view:
            f_tree_view.setSelectionMode(QAbstractItemView.MultiSelection)

        if file_dialog.exec():
            folders = file_dialog.selectedFiles()

            if len(folders) != 0:
                for folder in folders:
                    parent_folder = os.path.dirname(r"{}".format(folder))
                    self.mainwindow.options.save_user_defaults(music_folder=folder, last_folder_opened=parent_folder)
                    self.folder_list.addItem(folder)
                    self.folder_list.sortItems()

        # folder = QFileDialog.getExistingDirectory(self, "Add Folder(s)",
        #                                           self.mainwindow.options.get_default_last_folder_opened(),
        #                                           QFileDialog.ShowDirsOnly)

    def rm_clicked(self):
        if len(self.folder_list.selectedItems()) != 0:
            self.mainwindow.options.delete_music_folder(self.get_selected_item())
            self.remove_sel()
Пример #43
0
class Dimili(QMainWindow):

    def baslat(self, anaPencere):
        anaPencere.resize(600, 400)
        anaPencere.setWindowTitle("Dimili-Türkçe Sözlük")
        anaPencere.setFixedSize(600,400)

        icon =QIcon()
        icon.addPixmap(QPixmap("Dictionary.png"),QIcon.Normal,QIcon.Off)
        anaPencere.setWindowIcon(icon)
        zemin=QWidget(anaPencere)
        zemin.setGeometry(QRect(0,30,600,390))
        zemin.setStyleSheet("background-color:rgb(167, 196, 233);")
        self.araKutu = QLineEdit(anaPencere)
        self.araKutu.setGeometry(QRect(10, 80, 200, 20))

        self.araKutu.textChanged.connect(self.benzerKelimeler)


        self.kelimeGir = QLabel("Kelimeler:",anaPencere)
        self.kelimeGir.setGeometry(QRect(10, 110, 141, 21))

        self.kelimeGor = QLabel("Kelime Ara",anaPencere)
        self.kelimeGor.setGeometry(QRect(10, 30, 91, 16))
        self.harfGrup=QButtonGroup(anaPencere)
        aharf=QPushButton("â",anaPencere)
        aharf.setGeometry(QRect(10,50,25,25))
        eharf=QPushButton("é",anaPencere)
        eharf.setGeometry(QRect(30,50,25,25))

        self.DilGrup=QButtonGroup(anaPencere)
        self.Dil1 = QPushButton("Zazaca-Türkçe",anaPencere)
        self.Dil1.setGeometry(QRect(230, 80, 91, 23))
        self.Dil1.setCheckable(True)
        self.Dil1.setAutoExclusive(True)
        self.Dil1.setChecked(True)
        self.Dil1.setStyleSheet("background-color: rgb(102, 255, 0);")

        self.Dil2 = QPushButton("Türkçe-Zazaca",anaPencere)
        self.Dil2.setGeometry(QRect(330, 80, 91, 23))
        self.Dil2.setCheckable(True)
        self.Dil2.setAutoExclusive(True)
        self.Dil2.setStyleSheet("background-color: rgb(255, 94, 105);")

        self.DilGrup.addButton(self.Dil1,1)
        self.DilGrup.addButton(self.Dil2,2)
        self.DilGrup.buttonClicked[int].connect(self.dilSecme)
        self.kelimeListesi=QListWidget(anaPencere)
        self.kelimeListesi.setGeometry(QRect(10, 130, 191, 231))

        self.kelimeListesi.itemClicked.connect(self.kelimeAcikla)
        self.kelimeAnlam = QLabel("Kelimenin Anlamı:",anaPencere)
        self.kelimeAnlam.setGeometry(QRect(230, 110, 131, 21))

        self.cumleList1 = QListWidget(anaPencere)
        self.cumleList1.setGeometry(QRect(230, 130, 351, 51))

        self.ornekCumle1 = QLabel("Örnek Zazaca Cümle:",anaPencere)
        self.ornekCumle1.setGeometry(QRect(230, 200, 101, 21))

        self.cumleList2 = QListWidget(anaPencere)
        self.cumleList2.setGeometry(QRect(230, 220, 351, 51))

        self.ornekCumle2 = QLabel("Örnek Türkçe Cümle:",anaPencere)
        self.ornekCumle2.setGeometry(QRect(230, 290, 111, 16))

        self.cumleList3 = QListWidget(anaPencere)
        self.cumleList3.setGeometry(QRect(230, 310, 351, 51))




        self.anaMenu = QMenuBar(anaPencere)
        self.anaMenu.setGeometry(QRect(0, 0, 600, 21))

        self.menuDosya = QMenu("Dosya",self.anaMenu)

        self.menuDuzenle = QMenu("Düzenle",self.anaMenu)

        self.menuYardim = QMenu("Yardım",self.anaMenu)

        anaPencere.setMenuBar(self.anaMenu)

        self.durum = QStatusBar(zemin)
        anaPencere.setStatusBar(self.durum)
        self.durum.setStyleSheet("background-color:white")
        self.durum.showMessage("Hazır")

        self.cikis= QAction(QIcon("Exit.ico"),"&Çıkış",anaPencere)
        self.cikis.setShortcut("Ctrl+X")

        self.cikis.triggered.connect(anaPencere.close)

        self.actionHakkinda = QAction("Hakkında",anaPencere)
        self.actionHakkinda.triggered.connect(self.hakkinda)
        self.actionSecenekler = QAction("Seçenekler",anaPencere)

        self.menuDosya.addAction(self.cikis)
        self.menuDuzenle.addAction(self.actionSecenekler)
        self.menuYardim.addAction(self.actionHakkinda)
        self.anaMenu.addAction(self.menuDosya.menuAction())
        self.anaMenu.addAction(self.menuDuzenle.menuAction())
        self.anaMenu.addAction(self.menuYardim.menuAction())

    def kelimeAcikla(self):
        if self.DilGrup.checkedId()==1:
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()]
            for it in itemtext:
                itemtext=it
            self.im.execute("select Tur from DimTur where Zazaca=?",[itemtext])
            turliste=[tur[0] for tur in self.im.fetchall()]
            for tura in turliste:
                turliste=tura
            self.im.execute("select Turkce from DimTur where Zazaca=?",[itemtext])
            turkAnlam=[tur[0] for tur in self.im.fetchall()]
            for tr in turkAnlam:
                self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr)
            self.im.execute("select OrnekZazacaCumle from DimTur where Zazaca=?",[itemtext])
            ornekZaza=[zaza[0] for zaza in self.im.fetchall()]
            for za in ornekZaza:
                ornekZaza=za
            self.cumleList2.addItem(ornekZaza)
            self.im.execute("select OrnekTurkceCumle from DimTur where Zazaca=?",[itemtext])
            ornekTurk=[turk[0] for turk in self.im.fetchall()]
            for orn in ornekTurk:
                ornekTurk=orn
            self.cumleList3.addItem(ornekTurk)
        if self.DilGrup.checkedId()==2:
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()]
            for it in itemtext:
                itemtext=it
            self.im.execute("select Tur from DimTur where Turkce=?",[itemtext])
            turliste=[tur[0] for tur in self.im.fetchall()]
            for tura in turliste:
                turliste=tura
            self.im.execute("select Zazaca from DimTur where Turkce=?",[itemtext])
            zazaAnlam=[tur[0] for tur in self.im.fetchall()]
            for tr in zazaAnlam:
                self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr)
            self.im.execute("select OrnekZazacaCumle from DimTur where Turkce=?",[itemtext])
            ornekTurk=[turk[0] for turk in self.im.fetchall()]
            for orn in ornekTurk:
                ornekTurk=orn
            self.cumleList2.addItem(ornekTurk)
            self.im.execute("select OrnekTurkceCumle from DimTur where Turkce=?",[itemtext])
            ornekZaza=[zaza[0] for zaza in self.im.fetchall()]
            for za in ornekZaza:
                ornekZaza=za
            self.cumleList3.addItem(ornekZaza)




    def benzerKelimeler(self):
        if self.DilGrup.checkedId()==1:
            self.VT=sqlite3.connect("DimiliVT.sqlite")
            self.im=self.VT.cursor()
            self.kelimeListesi.clear()
            kelime=self.araKutu.text()
            if kelime=="" or kelime==None:
                self.kelimeListesi.clear()
            else:
                self.im.execute("select Zazaca from DimTur where Zazaca like ? order by Zazaca ",[kelime+'%'])
                zazaListe=[za[0] for za in self.im.fetchall()]
                for i in zazaListe:
                 self.kelimeListesi.addItem(i)

        if self.DilGrup.checkedId()==2:
            self.VT=sqlite3.connect("DimiliVT.sqlite")
            self.im=self.VT.cursor()
            kelime=self.araKutu.text()
            self.kelimeListesi.clear()
            if kelime=="" or kelime==None:
                self.kelimeListesi.clear()
            else:
                self.im.execute("select Turkce from DimTur where Turkce like ? ",[kelime+'%'])
                turkListe=[tu[0] for tu in self.im.fetchall()]
                for i in turkListe:
                  self.kelimeListesi.addItem(i)

    def dilSecme(self,ind):
        if ind==1:
            self.araKutu.setText("")
            self.kelimeListesi.clear()
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            self.Dil1.setStyleSheet("background:#66FF00")
            self.Dil2.setStyleSheet("background-color:#E41841")
        if ind==2:
            self.araKutu.setText("")
            self.kelimeListesi.clear()
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            self.Dil2.setStyleSheet("background:#66FF00")
            self.Dil1.setStyleSheet("background-color:#E41841")
    def hakkinda(self):
        QMessageBox.about(self, "Program Hakkında",
                "Bu program <b>bla bla</b> tarafından programlanmıştır. 2015")
Пример #44
0
class MetToolsDownloadManager(QWidget):
    def __init__(self, iface) -> None:
        super().__init__()

        self.iface = iface
        self.options = get_options()
        self.msg_bar = MessageBar(iface)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        hbox.addWidget(QLabel('Dataset: '))
        self.cbox_dataset = QComboBox()
        self.cbox_dataset.addItem('-')
        for index, (dataset_name,
                    dataset_label) in enumerate(met_datasets.items()):
            self.cbox_dataset.addItem(dataset_name, dataset_name)
            self.cbox_dataset.setItemData(index + 1, dataset_label,
                                          Qt.ToolTipRole)
        self.cbox_dataset.currentIndexChanged.connect(self.on_dataset_changed)
        hbox.addWidget(self.cbox_dataset)

        hbox_product_name = QHBoxLayout()
        vbox.addLayout(hbox_product_name)
        hbox_product_name.addWidget(QLabel('Product: '))
        self.cbox_product = QComboBox()
        self.cbox_product.currentIndexChanged.connect(self.on_product_changed)
        hbox_product_name.addWidget(self.cbox_product)

        hbox_start_datetime = QHBoxLayout()
        vbox.addLayout(hbox_start_datetime)
        self.dedit_start_date = QDateTimeEdit()
        self.dedit_start_date.setCalendarPopup(True)
        hbox_start_datetime.addWidget(QLabel('Start: '))
        hbox_start_datetime.addWidget(self.dedit_start_date)

        hbox_end_datetime = QHBoxLayout()
        vbox.addLayout(hbox_end_datetime)
        self.dedit_end_date = QDateTimeEdit()
        self.dedit_end_date.setCalendarPopup(True)
        hbox_end_datetime.addWidget(QLabel('End: '))
        hbox_end_datetime.addWidget(self.dedit_end_date)

        gbox_extent = QGroupBox('Extent')
        vbox.addWidget(gbox_extent)
        vbox_extent = QVBoxLayout()
        gbox_extent.setLayout(vbox_extent)

        hbox_extent = QHBoxLayout()
        vbox_extent.addLayout(hbox_extent)
        self.radio_global = QRadioButton('Global')
        self.radio_global.toggled.connect(self.on_extent_radio_button_clicked)
        hbox_extent.addWidget(self.radio_global)
        self.radio_subset = QRadioButton('Subset')
        self.radio_subset.toggled.connect(self.on_extent_radio_button_clicked)
        hbox_extent.addWidget(self.radio_subset)

        self.widget_extent = QWidget()
        vbox_extent.addWidget(self.widget_extent)
        grid_extent = QGridLayout()
        self.widget_extent.setLayout(grid_extent)
        self.widget_extent.hide()
        self.top = add_grid_lineedit(grid_extent,
                                     0,
                                     'North Latitude',
                                     LAT_VALIDATOR,
                                     '°',
                                     required=True)
        self.right = add_grid_lineedit(grid_extent,
                                       1,
                                       'East Longitude',
                                       LON_VALIDATOR,
                                       '°',
                                       required=True)
        self.left = add_grid_lineedit(grid_extent,
                                      2,
                                      'West Longitude',
                                      LON_VALIDATOR,
                                      '°',
                                      required=True)
        self.bottom = add_grid_lineedit(grid_extent,
                                        3,
                                        'South Latitude',
                                        LAT_VALIDATOR,
                                        '°',
                                        required=True)
        self.extent_from_active_layer = QPushButton('Set from Active Layer')
        grid_extent.addWidget(self.extent_from_active_layer, 4, 1)
        self.extent_from_active_layer.clicked.connect(
            self.on_extent_from_active_layer_button_clicked)
        self.radio_global.setChecked(True)

        self.tree = QListWidget()
        vbox_tree = QVBoxLayout()
        vbox.addLayout(vbox_tree)
        vbox_tree.addWidget(self.tree)

        self.btn_download = QPushButton('Download')
        self.btn_download.clicked.connect(self.on_download_button_clicked)
        vbox.addWidget(self.btn_download)

        self.progress_bar = QProgressBar()
        self.progress_bar.setTextVisible(False)
        self.progress_bar.hide()
        vbox.addWidget(self.progress_bar)

    def on_dataset_changed(self, index: int):
        self.cbox_product.clear()
        dataset_name = self.cbox_dataset.currentData()
        if dataset_name is None:
            return
        auth = (self.options.rda_username, self.options.rda_password)
        self.products = get_met_products(dataset_name, auth)
        for product in self.products.keys():
            self.cbox_product.addItem(product, product)

    def on_product_changed(self, index: int):
        if index == -1:
            return

        self.tree.clear()
        product_name = self.cbox_product.currentData()
        current_avail_vars = self.products[product_name]
        dates = []
        for name in current_avail_vars.keys():
            item = QListWidgetItem(current_avail_vars[name]['label'])
            item.setData(Qt.UserRole, name)
            item.setCheckState(Qt.Checked)
            self.tree.addItem(item)
            dates.append(current_avail_vars[name]['start_date'])
            dates.append(current_avail_vars[name]['end_date'])
        date_min = min(dates)
        date_max = max(dates)

        for dt_input in [self.dedit_start_date, self.dedit_end_date]:
            dt_input.setDateTimeRange(
                QDateTime(QDate(date_min.year, date_min.month, date_min.day),
                          QTime(date_min.hour, date_min.minute)),
                QDateTime(QDate(date_max.year, date_max.month, date_max.day),
                          QTime(date_max.hour, date_max.minute)))

        min_dt = self.dedit_start_date.minimumDateTime()
        max_dt = self.dedit_start_date.maximumDateTime()
        self.dedit_start_date.setDateTime(min_dt)
        self.dedit_end_date.setDateTime(max_dt)

    def on_download_button_clicked(self):
        param_names = []
        for index in range(self.tree.count()):
            item = self.tree.item(index)
            if item.checkState() == Qt.Checked:
                param_name = item.data(Qt.UserRole)
                param_names.append(param_name)

        dataset_name = self.cbox_dataset.currentData()
        product_name = self.cbox_product.currentData()
        start_date = self.dedit_start_date.dateTime().toPyDateTime()
        end_date = self.dedit_end_date.dateTime().toPyDateTime()

        args = [
            self.options.met_dir, dataset_name, product_name, start_date,
            end_date
        ]
        if is_met_dataset_downloaded(*args):
            reply = QMessageBox.question(self.iface.mainWindow(
            ), 'Existing dataset', (
                'You already downloaded data with the selected dataset/product/date/time combination. '
                'If you continue, this data will be removed.\n'
                'Location: {}'.format(get_met_dataset_path(*args))),
                                         QMessageBox.Ok, QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return

        lat_north = self.top.value()
        lat_south = self.bottom.value()
        lon_west = self.left.value()
        lon_east = self.right.value()
        auth = (self.options.rda_username, self.options.rda_password)

        thread = TaskThread(lambda: download_met_dataset(
            self.options.met_dir, auth, dataset_name, product_name,
            param_names, start_date, end_date, lat_south, lat_north, lon_west,
            lon_east),
                            yields_progress=True)
        thread.started.connect(self.on_started_download)
        thread.progress.connect(self.on_progress_download)
        thread.finished.connect(self.on_finished_download)
        thread.succeeded.connect(self.on_successful_download)
        thread.failed.connect(reraise)
        thread.start()

    def on_started_download(self) -> None:
        self.btn_download.hide()
        self.progress_bar.show()

    def on_progress_download(self, percent: int, status: str) -> None:
        self.progress_bar.setValue(percent)
        if status == 'submitted':
            self.msg_bar.info(
                'Met dataset download request submitted successfully, waiting until available for download...'
            )
        elif status == 'ready':
            self.msg_bar.info(
                'Met dataset download request is now ready, downloading...')
        else:
            print(status)

    def on_finished_download(self) -> None:
        self.btn_download.show()
        self.progress_bar.hide()

    def on_successful_download(self) -> None:
        self.msg_bar.success('Meteorological dataset downloaded successfully.')
        Broadcast.met_datasets_updated.emit()

    def on_extent_radio_button_clicked(self):
        if self.radio_global.isChecked():
            self.top.set_value(90)
            self.bottom.set_value(-90)
            self.left.set_value(-180)
            self.right.set_value(180)
            self.top.setDisabled(True)
            self.bottom.setDisabled(True)
            self.left.setDisabled(True)
            self.right.setDisabled(True)
            self.widget_extent.hide()

        elif self.radio_subset.isChecked():
            self.widget_extent.show()
            self.top.setDisabled(False)
            self.bottom.setDisabled(False)
            self.left.setDisabled(False)
            self.right.setDisabled(False)

    def on_extent_from_active_layer_button_clicked(self):
        layer = self.iface.activeLayer()  # type: Optional[QgsMapLayer]
        if layer is None:
            return
        layer_crs = CRS(layer.crs().toProj4())
        target_crs = CRS('+proj=latlong +datum=WGS84')
        extent = layer.extent()  # type: QgsRectangle
        bbox = rect_to_bbox(extent)
        bbox_geo = layer_crs.transform_bbox(bbox, target_crs.srs)
        padding = 5  # degrees
        lat_south = max(bbox_geo.miny - 5, -90)
        lat_north = min(bbox_geo.maxy + 5, 90)
        lon_west = max(bbox_geo.minx - 5, -180)
        lon_east = min(bbox_geo.maxx + 5, 180)
        self.bottom.set_value(lat_south)
        self.top.set_value(lat_north)
        self.left.set_value(lon_west)
        self.right.set_value(lon_east)
class Theme(QWidget):
    """Theme widget class."""

    def __init__(self, parent):
        super(Theme, self).__init__()
        self._preferences, vbox = parent, QVBoxLayout(self)
        vbox.addWidget(QLabel(self.tr("<b>Select Theme:</b>")))
        self.list_skins = QListWidget()
        self.list_skins.setSelectionMode(QListWidget.SingleSelection)
        vbox.addWidget(self.list_skins)
        self.btn_delete = QPushButton(self.tr("Delete Theme"))
        self.btn_preview = QPushButton(self.tr("Preview Theme"))
        self.btn_create = QPushButton(self.tr("Create Theme"))
        hbox = QHBoxLayout()
        hbox.addWidget(self.btn_delete)
        hbox.addSpacerItem(QSpacerItem(10, 0, QSizePolicy.Expanding,
                           QSizePolicy.Fixed))
        hbox.addWidget(self.btn_preview)
        hbox.addWidget(self.btn_create)
        vbox.addLayout(hbox)
        self._refresh_list()

        self.btn_preview.clicked['bool'].connect(self.preview_theme)
        self.btn_delete.clicked['bool'].connect(self.delete_theme)
        self.btn_create.clicked['bool'].connect(self.create_theme)

        self._preferences.savePreferences.connect(self.save)

    def delete_theme(self):
        if self.list_skins.currentRow() != 0:
            file_name = ("%s.qss" % self.list_skins.currentItem().text())
            qss_file = file_manager.create_path(resources.NINJA_THEME_DOWNLOAD,
                                                file_name)
            file_manager.delete_file(qss_file)
            self._refresh_list()

    def create_theme(self):
        designer = preferences_theme_editor.ThemeEditor(self)
        designer.exec_()
        self._refresh_list()

    def showEvent(self, event):
        self._refresh_list()
        super(Theme, self).showEvent(event)

    def _refresh_list(self):
        self.list_skins.clear()
        self.list_skins.addItem("Default")

        files = [file_manager.get_file_name(filename) for filename in
                 file_manager.get_files_from_folder(
                     resources.NINJA_THEME_DOWNLOAD, "qss")]
        files.sort()
        self.list_skins.addItems(files)

        if settings.NINJA_SKIN in files:
            index = files.index(settings.NINJA_SKIN)
            self.list_skins.setCurrentRow(index + 1)
        else:
            self.list_skins.setCurrentRow(0)

    def save(self):
        qsettings = IDE.ninja_settings()
        settings.NINJA_SKIN = self.list_skins.currentItem().text()
        qsettings.setValue("preferences/theme/skin", settings.NINJA_SKIN)
        self.preview_theme()

    def preview_theme(self):
        if self.list_skins.currentRow() == 0:
            qss_file = resources.NINJA_THEME
        else:
            file_name = ("%s.qss" % self.list_skins.currentItem().text())
            qss_file = file_manager.create_path(resources.NINJA_THEME_DOWNLOAD,
                                                file_name)
        with open(qss_file) as f:
            qss = f.read()
        QApplication.instance().setStyleSheet(qss)
Пример #46
0
class EasyQListSuite(QWidget):
    """
    Provide a window that has a QListWidget with 'Add' and 'Remove' button.
    """
    def __init__(self, *__args):
        super(EasyQListSuite, self).__init__(*__args)

        self.__item_list = []

        self.__list_main = QListWidget(self)
        self.__button_add = QPushButton('Add')
        self.__button_remove = QPushButton('Remove')

        self.__init_ui()
        self.__config_ui()

    def update_item(self, items: [(str, any)]):
        """
        Specify a (key, value) tuple list.
            Key will be displayed as list item.
            Value can be retrieved by get_select_items()
        :param items: Specify a (key, value) tuple list.
        :return: None
        """
        self.__item_list.clear()
        for item in items:
            if isinstance(item, (list, tuple)):
                if len(item) == 0:
                    continue
                elif len(item) == 1:
                    self.__item_list.append((str(item[0]), item[0]))
                else:
                    self.__item_list.append((str(item[0]), item[1]))
            else:
                self.__item_list.append((str(item), item))
        self.__update_list()

    def get_select_items(self) -> [any]:
        """
        Get the value of the items that user selected.
        :return: The value of the items that user selected.
        """
        return [item.data(Qt.UserRole) for item in self.__list_main.selectedItems()]

    def set_add_handler(self, handler):
        """
        Add a handler for 'Add' button clicking
        :param handler: The handler that connects to the button clicked signal
        :return:
        """
        self.__button_add.clicked.connect(handler)

    def set_remove_handler(self, handler):
        """
        Add a handler for 'Remove' button clicking
        :param handler: The handler that connects to the button clicked signal
        :return:
        """
        self.__button_remove.clicked.connect(handler)

    # ---------------------------------------- Private ----------------------------------------

    def __init_ui(self):
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)

        line_layout = QHBoxLayout()
        line_layout.addWidget(self.__button_add)
        line_layout.addWidget(self.__button_remove)

        main_layout.addWidget(self.__list_main)
        main_layout.addLayout(line_layout)

    def __config_ui(self):
        pass

    def __update_list(self):
        self.__list_main.clear()
        for text, obj in self.__item_list:
            item = QListWidgetItem()
            item.setText(text)
            item.setData(Qt.UserRole, obj)
            self.__list_main.addItem(item)
Пример #47
0
class SessionsManager(QDialog):

    """Session Manager, to load different configurations of ninja."""

    def __init__(self, parent=None):
        super(SessionsManager, self).__init__(parent, Qt.Dialog)
        self._ide = parent
        self.setWindowTitle(translations.TR_SESSIONS_TITLE)
        self.setMinimumWidth(400)
        vbox = QVBoxLayout(self)
        vbox.addWidget(QLabel(translations.TR_SESSIONS_DIALOG_BODY))
        self.sessionList = QListWidget()
        self.sessionList.addItems([key for key in settings.SESSIONS])
        self.sessionList.setCurrentRow(0)
        self.contentList = QListWidget()
        self.btnDelete = QPushButton(translations.TR_SESSIONS_BTN_DELETE)
        self.btnDelete.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btnUpdate = QPushButton(translations.TR_SESSIONS_BTN_UPDATE)
        self.btnUpdate.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btnCreate = QPushButton(translations.TR_SESSIONS_BTN_CREATE)
        self.btnCreate.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btnOpen = QPushButton(translations.TR_SESSIONS_BTN_ACTIVATE)
        self.btnOpen.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.btnOpen.setDefault(True)
        hbox = QHBoxLayout()
        hbox.addWidget(self.btnDelete)
        hbox.addWidget(self.btnUpdate)
        hbox.addWidget(self.btnCreate)
        hbox.addWidget(self.btnOpen)

        vbox.addWidget(self.sessionList)
        vbox.addWidget(self.contentList)
        vbox.addLayout(hbox)

        self.sessionList.itemSelectionChanged.connect(self.load_session_content)
        self.btnOpen.clicked['bool'].connect(self.open_session)
        self.btnUpdate.clicked['bool'].connect(self.save_session)
        self.btnCreate.clicked['bool'].connect(self.create_session)
        self.btnDelete.clicked['bool'].connect(self.delete_session)
        self.load_session_content()

    def load_session_content(self):
        """Load the selected session, replacing the current session."""
        item = self.sessionList.currentItem()
        self.contentList.clear()
        if item is not None:
            key = item.text()
            files = [translations.TR_FILES] + \
                [file[0] for file in settings.SESSIONS[key][0]]
            projects = [translations.TR_PROJECT] + settings.SESSIONS[key][1]
            content = files + projects
            self.contentList.addItems(content)

    def create_session(self):
        """Create a new Session."""
        sessionInfo = QInputDialog.getText(None,
            translations.TR_SESSIONS_CREATE_TITLE,
            translations.TR_SESSIONS_CREATE_BODY)
        if sessionInfo[1]:
            sessionName = sessionInfo[0]
            if not sessionName or sessionName in settings.SESSIONS:
                QMessageBox.information(self,
                    translations.TR_SESSIONS_MESSAGE_TITLE,
                    translations.TR_SESSIONS_MESSAGE_BODY)
                return
            SessionsManager.save_session_data(sessionName, self._ide)
        self._ide.Session = sessionName
        self.close()

    @classmethod
    def save_session_data(cls, sessionName, ide):
        """Save the updates from a session."""
        openedFiles = ide.filesystem.get_files()
        files_info = []
        for path in openedFiles:
            editable = ide.get_or_create_editable(path)
            if editable.is_dirty:
                stat_value = 0
            else:
                stat_value = os.stat(path).st_mtime
            files_info.append([path,
                               editable.editor.getCursorPosition(), stat_value])
        projects_obj = ide.filesystem.get_projects()
        projects = [projects_obj[proj].path for proj in projects_obj]
        settings.SESSIONS[sessionName] = [files_info, projects]
        qsettings = ide.data_settings()
        qsettings.setValue('ide/sessions', settings.SESSIONS)

    def save_session(self):
        """Save current session"""
        if self.sessionList.currentItem():
            sessionName = self.sessionList.currentItem().text()
            SessionsManager.save_session_data(sessionName, self._ide)
            self._ide.show_message(translations.TR_SESSIONS_UPDATED_NOTIF %
                                   {'session': sessionName}, 2000)
            self.load_session_content()

    def open_session(self):
        """Open a saved session"""
        if self.sessionList.currentItem():
            key = self.sessionList.currentItem().text()
            self._load_session_data(key)
            self._ide.Session = key
            self.close()

    def delete_session(self):
        """Delete a session"""
        if self.sessionList.currentItem():
            key = self.sessionList.currentItem().text()
            settings.SESSIONS.pop(key)
            self.sessionList.takeItem(self.sessionList.currentRow())
            self.contentList.clear()
            qsettings = self._ide.data_settings()
            qsettings.setValue('ide/sessions', settings.SESSIONS)

    def _load_session_data(self, key):
        """Activate the selected session, closing the current files/projects"""
        main_container = self._ide.get_service('main_container')
        projects_explorer = self._ide.get_service('projects_explorer')
        if projects_explorer and main_container:
            projects_explorer.close_opened_projects()
            for fileData in settings.SESSIONS[key][0]:
                path, line, stat_value = fileData
                if file_manager.file_exists(path):
                    mtime = os.stat(path).st_mtime
                    ignore_checkers = (mtime == stat_value)
                    main_container.open_file(path, line,
                                             ignore_checkers=ignore_checkers)
            if projects_explorer:
                projects_explorer.load_session_projects(
                    settings.SESSIONS[key][1])
class CustomMetDatasetDialog(QDialog):
    def __init__(self, vtable_dir: str, spec: Optional[dict] = None) -> None:
        super().__init__()

        self.vtable_dir = vtable_dir
        self.paths = set()  # type: Set[Path]

        geom = QGuiApplication.primaryScreen().geometry()
        w, h = geom.width(), geom.height()
        self.setWindowTitle("Custom Meteorological Dataset")
        self.setMinimumSize(w * 0.25, h * 0.35)

        layout = QVBoxLayout()

        # button to open folder/files dialog
        hbox = QHBoxLayout()
        layout.addLayout(hbox)
        add_folder_btn = QPushButton('Add folder')
        add_files_btn = QPushButton('Add files')
        remove_selected_btn = QPushButton('Remove selected')
        hbox.addWidget(add_folder_btn)
        hbox.addWidget(add_files_btn)
        hbox.addWidget(remove_selected_btn)
        add_folder_btn.clicked.connect(self.on_add_folder_btn_clicked)
        add_files_btn.clicked.connect(self.on_add_files_btn_clicked)
        remove_selected_btn.clicked.connect(
            self.on_remove_selected_btn_clicked)

        # show added files in a list
        self.paths_list = QListWidget()
        self.paths_list.setSelectionMode(QAbstractItemView.ContiguousSelection)
        layout.addWidget(self.paths_list)

        grid = QGridLayout()
        layout.addLayout(grid)

        # date/time start/end
        self.start_date_input = QDateTimeEdit()
        self.start_date_input.setCalendarPopup(True)

        self.end_date_input = QDateTimeEdit()
        self.end_date_input.setCalendarPopup(True)

        add_grid_labeled_widget(grid, 0, 'Start Date/Time',
                                self.start_date_input)
        add_grid_labeled_widget(grid, 1, 'End Date/Time', self.end_date_input)

        # interval in seconds
        interval_validator = QIntValidator()
        interval_validator.setBottom(1)
        self.interval_input = add_grid_lineedit(grid,
                                                2,
                                                'Interval in seconds',
                                                interval_validator,
                                                required=True)

        # vtable file input
        self.vtable_input, vtable_hbox = create_file_input(
            dialog_caption='Select VTable file',
            is_folder=False,
            start_folder=vtable_dir)
        add_grid_labeled_widget(grid, 3, 'VTable', vtable_hbox)

        btn_box = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self.on_ok_clicked)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)

        self.setLayout(layout)

        if spec:
            self.paths = set(map(Path, spec['paths']))
            self.base_folder = spec['base_folder']
            self.update_file_list()

            start_date, end_date = spec['time_range']
            for date_input, date in [(self.start_date_input, start_date),
                                     (self.end_date_input, end_date)]:
                date_input.setDateTime(
                    QDateTime(QDate(date.year, date.month, date.day),
                              QTime(date.hour, date.minute)))

            self.interval_input.set_value(spec['interval_seconds'])

            self.vtable_input.setText(spec['vtable'])

    @property
    def start_date(self) -> datetime:
        return self.start_date_input.dateTime().toPyDateTime()

    @property
    def end_date(self) -> datetime:
        return self.end_date_input.dateTime().toPyDateTime()

    @property
    def interval_seconds(self) -> int:
        return self.interval_input.value()

    @property
    def vtable_path(self) -> str:
        return self.vtable_input.text()

    def on_ok_clicked(self) -> None:
        if not self.paths:
            raise UserError('No GRIB files were added')
        if not self.interval_input.is_valid():
            raise UserError('Interval must be an integer above 0')
        if self.start_date == self.end_date:
            raise UserError('Start date cannot be the same as end date')
        if self.start_date > self.end_date:
            raise UserError('Start date cannot be after the end date')
        if not self.vtable_path:
            raise UserError('No VTable file selected')
        if not os.path.exists(os.path.join(self.vtable_dir, self.vtable_path)):
            raise UserError('VTable file does not exist')
        self.accept()

    def on_add_folder_btn_clicked(self) -> None:
        folder = QFileDialog.getExistingDirectory(caption='Select folder')
        if not folder:
            return
        paths = []  # type: List[Path]
        for root, _, filenames in os.walk(folder):
            paths.extend(Path(root) / filename for filename in filenames)
        self.update_paths(self.paths.union(paths))
        self.update_file_list()

    def on_add_files_btn_clicked(self) -> None:
        paths, _ = QFileDialog.getOpenFileNames(caption='Select files')
        if not paths:
            return

        self.update_paths(self.paths.union(map(Path, paths)))
        self.update_file_list()

    def on_remove_selected_btn_clicked(self) -> None:
        paths = [
            item.data(Qt.UserRole) for item in self.paths_list.selectedItems()
        ]
        self.update_paths(self.paths.difference(paths))
        self.update_file_list()

    def update_paths(self, paths: Set[Path]) -> None:
        if len(paths) == 1:
            # special case as os.path.commonpath() would return '.'
            base_folder = os.path.dirname(list(paths)[0])
        elif paths:
            try:
                base_folder = os.path.commonpath(paths)
            except ValueError:
                raise UnsupportedError(
                    'Only datasets with files located on the same drive are supported'
                )
        else:
            base_folder = None

        self.base_folder = base_folder
        self.paths = paths

    def update_file_list(self) -> None:
        self.paths_list.clear()
        for path in sorted(self.paths):
            item = QListWidgetItem(str(path))
            item.setData(Qt.UserRole, path)
            self.paths_list.addItem(item)
Пример #49
0
class ResumeBox(QGroupBox):

    restartRequested = pyqtSignal(QWidget)

    def __init__(self, parent):
        super(ResumeBox, self).__init__(parent)
        self.engine = None
        self.game = None
        self.parent = parent
        self.matches = []
        self.initUI()

    def initUI(self):
        self.widgetLayout = QVBoxLayout(self)
        self.savedlist = QListWidget(self)
        self.savedlist.setSelectionMode(
            QAbstractItemView.SingleSelection)
        self.savedlist.hide()
        self.widgetLayout.addWidget(self.savedlist)
        self.buttonLayout = QHBoxLayout()
        self.widgetLayout.addLayout(self.buttonLayout)
        self.resumebutton = QPushButton(self)
        self.resumebutton.clicked.connect(self.resumeGame)
        self.resumebutton.hide()
        self.buttonLayout.addWidget(self.resumebutton)
        self.cancelbutton = QPushButton(self)
        self.cancelbutton.clicked.connect(self.deleteGame)
        self.cancelbutton.hide()
        self.buttonLayout.addWidget(self.cancelbutton)
        self.emptyLabel = QLabel(self)
        self.widgetLayout.addWidget(self.emptyLabel)
        self.retranslateUI()

    def retranslateUI(self):
        self.setTitle(i18n(
            "ResumeBox", 'Saved Games'))
        self.resumebutton.setText(
            i18n("ResumeBox", 'Resume'))
        self.cancelbutton.setText(
            i18n("ResumeBox", 'Cancel'))
        self.emptyLabel.setText(i18n(
            "ResumeBox", 'No matches to be resumed'))

    def changeGame(self, game):
        self.game = game
        self.engine = ResumeEngine(game)
        self.savedlist.clear()
        self.matches = []
        candidates = self.engine.getCandidates()
        if not candidates:
            self.savedlist.hide()
            self.resumebutton.hide()
            self.cancelbutton.hide()
            self.emptyLabel.show()
        else:
            self.emptyLabel.hide()
            for idMatch, candidate in candidates.items():
                self.matches.append(idMatch)
                savedtime = datetime.datetime.strptime(
                    candidate['started'], "%Y-%m-%d %H:%M:%S.%f")
                strtime = savedtime.strftime("%Y-%m-%d %H:%M:%S")
                hours, remainder = divmod(int(candidate['elapsed']), 3600)
                minutes, seconds = divmod(remainder, 60)
                strelapsed = "{0:02}:{1:02}:{2:02}".format(
                    hours, minutes, seconds)
                msg = i18n("ResumeBox",
                           'Saved on {}. Time played: {}').format(strtime,
                                                                  strelapsed)
                item = QListWidgetItem(msg, self.savedlist)
                playerlist = ""
                for player in candidate['players']:
                    playerlist += "\n  " + player
                item.setToolTip(i18n(
                    "ResumeBox", "Players: {}").format(playerlist))
                self.savedlist.addItem(item)
            self.savedlist.show()
            self.resumebutton.show()
            self.cancelbutton.show()

    def resumeGame(self):
        selected = self.savedlist.selectedIndexes()
        if len(selected) > 0:
            idMatch = self.matches[selected[0].row()]
            gameengine = self.engine.resume(idMatch)
            matchTab = GameWidgetFactory.resumeGameWidget(
                self.game, gameengine, self.parent)
            if matchTab:
                matchTab.closeRequested.connect(self.parent.removeTab)
                matchTab.restartRequested.connect(self.restartGame)
                self.parent.newTab(matchTab, self.game)

    def restartGame(self, gamewidget):
        self.restartRequested.emit(gamewidget)

    def deleteGame(self):
        selected = self.savedlist.selectedIndexes()
        if len(selected) > 0:
            idMatch = self.matches[selected[0].row()]
            tit = i18n("ResumeBox", 'Cancel Saved Game')
            msg = i18n("ResumeBox",
                       "Are you sure you want to cancel saved game?")
            reply = QMessageBox.question(self, tit, msg,
                                         QMessageBox.Yes | QMessageBox.No,
                                         QMessageBox.No)

            if reply == QMessageBox.No:
                return False
            gameengine = self.engine.resume(idMatch)
            gameengine.cancelMatch()
            self.changeGame(self.game)
Пример #50
0
class Links(BottomTab):
    """This part will show the files which have a link with the current file"""
    def __init__(self, parent, path=None, window=None):
        BottomTab.__init__(self, parent)
        self.path = path
        self.window = window
        self.layout = QVBoxLayout(self)
        """Building of interface"""
        #Top
        self.top = QWidget(self)
        self.topLayout = QHBoxLayout(self.top)
        self.labelProjectName = QLabel("Projet : ", self.top)
        self.labelProjectName.setObjectName("label1_links")
        self.projectName = QLabel("Aucun", self.top)
        self.projectName.setObjectName("content1_links")
        self.labelName = QLabel("Nom : ", self.top)
        self.labelName.setObjectName("label2_links")
        self.name = QLabel("Inconnu", self.top)
        self.name.setObjectName("content2_links")
        self.labelType = QLabel("Type : ", self.top)
        self.labelType.setObjectName("label3_links")
        self.type = QLabel("Inconnu", self.top)
        self.type.setObjectName("content3_links")
        self.topLayout.addWidget(self.labelProjectName)
        self.topLayout.addWidget(self.projectName)
        self.topLayout.addWidget(self.labelName)
        self.topLayout.addWidget(self.name)
        self.topLayout.addWidget(self.labelType)
        self.topLayout.addWidget(self.type)
        spacer = QSpacerItem(250, 20)
        self.topLayout.addItem(spacer)
        self.layout.addWidget(self.top, 1)
        #Bottom
        self.bottom = QWidget(self)
        self.bottomLayout = QHBoxLayout(self.bottom)
        self.mainFiles = QGroupBox(self.tr("Fichiers principaux liés"),
                                   self.bottom)
        self.mainFiles.setObjectName("list1_links")
        self.mainFilesList = QListWidget(self.mainFiles)
        mfLayout = QVBoxLayout(self.mainFiles)
        mfLayout.addWidget(self.mainFilesList)

        self.styleFiles = QGroupBox(self.tr("Styles liés"), self.bottom)
        self.styleFiles.setObjectName("list2_links")
        self.styleFilesList = QListWidget(self.styleFiles)
        stfLayout = QVBoxLayout(self.styleFiles)
        stfLayout.addWidget(self.styleFilesList)

        self.scriptFiles = QGroupBox(self.tr("Scripts liés"), self.bottom)
        self.scriptFiles.setObjectName("list3_links")
        self.scriptFilesList = QListWidget(self.scriptFiles)
        scfLayout = QVBoxLayout(self.scriptFiles)
        scfLayout.addWidget(self.scriptFilesList)

        self.details = QGroupBox(self.tr("Détails"), self.bottom)
        self.chemin_det = QLabel(self.details)
        dLayout = QVBoxLayout(self.details)
        dLayout.addWidget(self.chemin_det)
        self.bottomLayout.addWidget(self.mainFiles)
        self.bottomLayout.addWidget(self.styleFiles)
        self.bottomLayout.addWidget(self.scriptFiles)
        self.bottomLayout.addWidget(self.details)
        self.layout.addWidget(self.bottom, 3)
        self.setStyleSheet("""
            *{font-family:calibri;}
            QLabel{max-height:35px;font-size:15px;}
            QLabel#label1_links, QLabel#label2_links, QLabel#label3_links{max-width:70px;}
            QLabel#content1_links, QLabel#content2_links, QLabel#content3_links{font-weight:bold;}
            #list1_links,#list2_links,#list3_links{max-width:250px;}
        """)

        self.refresh(path)

    def refresh(self, path=None):
        if path is not None:
            self.path = path
        #Nettoyage de listes et des champs
        self.projectName.setText("Aucun")
        self.name.setText("Inconnu")
        self.type.setText("Inconnu")
        self.mainFilesList.clear()
        self.styleFilesList.clear()
        self.scriptFilesList.clear()
        self.chemin_det.setText("")
        if self.path is not None:
            if os.path.isfile(self.path):
                file = UserFile(self.path)
                self.name.setText(file.name())
                isProjectFile, projectFile = False, None
                projects = self.window.opennedProjects
                project = None
                for p in projects:
                    isProjectFile, projectFile = p.isProjectFile(self.path)
                    if isProjectFile:
                        project = p
                if isProjectFile:
                    self.projectName.setText(project.name)
                    self.type.setText(projectFile.type)
                    for pf in projectFile.links[ProjectFile.MAIN_FILE]:
                        item = QListWidgetItem(pf.name)
                        item.projectFile = pf
                        self.mainFilesList.addItem(item)
                    for pf in projectFile.links[ProjectFile.STYLE_FILE]:
                        item = QListWidgetItem(pf.name)
                        item.projectFile = pf
                        self.styleFilesList.addItem(item)
                    for pf in projectFile.links[ProjectFile.SCRIPT_FILE]:
                        item = QListWidgetItem(pf.name)
                        item.projectFile = pf
                        self.scriptFilesList.addItem(item)
                    self.mainFilesList.itemClicked.connect(
                        self.on_widgetList_itemClicked)
                    self.styleFilesList.itemClicked.connect(
                        self.on_widgetList_itemClicked)
                    self.scriptFilesList.itemClicked.connect(
                        self.on_widgetList_itemClicked)

    def on_widgetList_itemClicked(self, item):
        projectFile = item.projectFile
        self.chemin_det.setText(self.tr("Chemin : ") + projectFile.path)
Пример #51
0
class FindDialog(QDialog):
    alphabetical = [dict(type="alphabetical", allowPseudoUnicode=True)]

    def __init__(self, currentGlyph, parent=None):
        super().__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowTitle(self.tr("Find…"))
        self.font = currentGlyph.font
        self._sortedGlyphNames = self.font.unicodeData.sortGlyphNames(self.font.keys(), self.alphabetical)

        layout = QGridLayout(self)
        self.glyphLabel = QLabel(self.tr("Glyph:"), self)
        self.glyphEdit = QLineEdit(self)
        self.glyphEdit.textChanged.connect(self.updateGlyphList)
        self.glyphEdit.event = self.lineEvent
        self.glyphEdit.keyPressEvent = self.lineKeyPressEvent

        self.beginsWithBox = QRadioButton(self.tr("Begins with"), self)
        self.containsBox = QRadioButton(self.tr("Contains"), self)
        self.beginsWithBox.setChecked(True)
        self.beginsWithBox.toggled.connect(self.updateGlyphList)

        self.glyphList = QListWidget(self)
        self.glyphList.itemDoubleClicked.connect(self.accept)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        l = 0
        layout.addWidget(self.glyphLabel, l, 0, 1, 2)
        layout.addWidget(self.glyphEdit, l, 2, 1, 4)
        l += 1
        layout.addWidget(self.beginsWithBox, l, 0, 1, 3)
        layout.addWidget(self.containsBox, l, 3, 1, 3)
        l += 1
        layout.addWidget(self.glyphList, l, 0, 1, 6)
        l += 1
        layout.addWidget(buttonBox, l, 0, 1, 6)
        self.setLayout(layout)
        self.updateGlyphList()

    def lineEvent(self, event):
        if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
            if self.beginsWithBox.isChecked():
                self.containsBox.toggle()
            else:
                self.beginsWithBox.toggle()
            return True
        else:
            return QLineEdit.event(self.glyphEdit, event)

    def lineKeyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_Up or key == Qt.Key_Down:
            self.glyphList.keyPressEvent(event)
        else:
            QLineEdit.keyPressEvent(self.glyphEdit, event)

    def updateGlyphList(self):
        beginsWith = self.beginsWithBox.isChecked()
        self.glyphList.clear()
        if not self.glyphEdit.isModified():
            self.glyphList.addItems(self._sortedGlyphNames)
        else:
            text = self.glyphEdit.text()
            if beginsWith:
                glyphs = [glyphName for glyphName in self._sortedGlyphNames if glyphName and glyphName.startswith(text)]
            else:
                glyphs = [glyphName for glyphName in self._sortedGlyphNames if glyphName and text in glyphName]
            self.glyphList.addItems(glyphs)
        self.glyphList.setCurrentRow(0)

    @classmethod
    def getNewGlyph(cls, parent, currentGlyph):
        dialog = cls(currentGlyph, parent)
        result = dialog.exec_()
        currentItem = dialog.glyphList.currentItem()
        newGlyph = None
        if currentItem is not None:
            newGlyphName = currentItem.text()
            if newGlyphName in dialog.font:
                newGlyph = dialog.font[newGlyphName]
        return (newGlyph, result)
Пример #52
0
class RecipeData(QWidget):
    def __init__(self):
        super().__init__()

        self.current_item = 0
        self.shopping_list_item = 0

        grid = QGridLayout()
        grid.setSpacing(15)

        # - - - Widgets - - -

        type_label = QLabel('Type:')
        type_label.setFixedWidth(250)
        type_combo_box = QComboBox(self)
        type_combo_box.setFixedWidth(250)
        combobox_items = ['All', 'Starter', 'Snacks', 'Breakfast', 'Lunch/Dinner']
        type_combo_box.addItems(combobox_items)
        search_label = QLabel('Search:')
        search_label.setFixedWidth(250)
        search_input = QLineEdit()
        search_input.setFixedWidth(250)
        self.list_box = QListWidget()
        self.list_box.setFixedWidth(250)

        # New recipe button
        self.new_recipe_button = QPushButton()
        self.new_recipe_button.setIcon(QIcon('add.png'))
        self.new_recipe_button.setIconSize(QSize(28, 28))
        self.new_recipe_button.setMaximumSize(32, 32)
        self.new_recipe_button.setStyleSheet("background-color: white")
        self.new_recipe_button.setStatusTip('Add New Recipe.')
        self.new_recipe_button.clicked.connect(lambda: add_new_recipe())

        # Add to shopping list button
        self.add_to_shopping_button = QPushButton()
        self.add_to_shopping_button.setIcon(QIcon('shopping.png'))
        self.add_to_shopping_button.setIconSize(QSize(32, 32))
        self.add_to_shopping_button.setMaximumSize(32, 32)
        self.add_to_shopping_button.setStyleSheet("background-color: white")
        self.add_to_shopping_button.setStatusTip('Add Recipe To Shopping List.')
        self.add_to_shopping_button.clicked.connect(lambda: self.add_to_shopping_list())

        # Refresh data button
        self.refresh_button = QPushButton()
        self.refresh_button.setIcon(QIcon('refresh.png'))
        self.refresh_button.setIconSize(QSize(26, 26))
        self.refresh_button.setMaximumSize(32, 32)
        self.refresh_button.setStyleSheet("background-color: white")
        self.refresh_button.setStatusTip('Refresh List.')

        # Delete recipe button
        self.delete_button = QPushButton()
        self.delete_button.setIcon(QIcon('delete.png'))
        self.delete_button.setIconSize(QSize(28, 28))
        self.delete_button.setMaximumSize(32, 32)
        self.delete_button.setStyleSheet("background-color: white")
        self.delete_button.setStatusTip('Delete Recipe.')
        self.delete_button.clicked.connect(lambda: self.delete_recipe())

        self.text_area = QTabWidget()
        self.text_area.tab1 = QTextEdit()
        self.text_area.tab2 = EditRecipe()

        self.text_area.addTab(self.text_area.tab1, 'Display')
        self.text_area.addTab(self.text_area.tab2, 'Edit')

        # Layout of widgets on grid
        grid.addWidget(type_label, 0, 0,)
        grid.addWidget(type_combo_box, 1, 0)
        grid.addWidget(search_label, 2, 0)
        grid.addWidget(search_input, 3, 0)
        grid.addWidget(self.list_box, 4, 0)

        grid.addWidget(self.new_recipe_button, 0, 1)
        grid.addWidget(self.add_to_shopping_button, 1, 1)
        grid.addWidget(self.refresh_button, 2, 1)
        grid.addWidget(self.delete_button, 3, 1)
        grid.addWidget(self.text_area, 0, 2, 5, 1)

        self.setLayout(grid)

        self.populate_recipe_list()

    def populate_recipe_list(self):
        self.list_box.clear()
        recipe_names = SQL_reader.recipe_names()
        for name in recipe_names:
            QListWidgetItem(str(name), self.list_box)

        self.list_box.itemClicked.connect(self.show_recipe)

    def show_recipe(self, item):
        title, ingredients, instructions = SQL_reader.recipe_data(item.text())
        recipe_text = html_print.display_output(title, ingredients, instructions)
        self.text_area.tab1.setHtml(recipe_text)
        self.shopping_list_item = item
        self.current_item = item.text()
        return

    def add_to_shopping_list(self):
        ShoppingList.add_recipe(main_window.window_content.tab2, self.current_item)

    def delete_recipe(self):
        SQL_reader.delete_function(self.current_item)
        self.populate_recipe_list()
Пример #53
0
class ImePanel(QWidget):
    def __init__(self, inputMethodManager):
        super().__init__()
        self.imm = inputMethodManager
        self.qLineImmDict = {}
        self.initUI()

    def getIMM(self):
        return self.imm

    def initUI(self):
        self.resize(800, 600)
        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        subvbox = QVBoxLayout()

        subhbox = QHBoxLayout()
        label = QLabel('当前状态:', self)
        subhbox.addWidget(label)
        self.stateNameEditBox = QLineEdit(self)
        self.stateNameEditBox.setReadOnly(True)
        subhbox.addWidget(self.stateNameEditBox)
        subhbox.setStretchFactor(self.stateNameEditBox, 2)
        self.qLineImmDict[self.stateNameEditBox] = 'currStateName'
        subvbox.addLayout(subhbox)
 
        subhbox = QHBoxLayout()
        label = QLabel('光标位置:', self)
        subhbox.addWidget(label)
        self.cursorPosEditBox = QLineEdit(self)
        self.cursorPosEditBox.setReadOnly(True)
        self.cursorPosEditBox.resize(100, 30)
        subhbox.addWidget(self.cursorPosEditBox)
        subvbox.addLayout(subhbox)
        self.qLineImmDict[self.cursorPosEditBox] = 'cursorPos'
 
        subhbox = QHBoxLayout()
        label = QLabel('上屏串:', self)
        subhbox.addWidget(label)
        self.completedEditBox = QLineEdit(self)
        self.completedEditBox.setReadOnly(True)
        subhbox.addWidget(self.completedEditBox)
        subvbox.addLayout(subhbox)  # 行---------------------
        self.qLineImmDict[self.completedEditBox] = 'Completed'
  
        subhbox = QHBoxLayout()
        label = QLabel('输入串:', self)
        subhbox.addWidget(label)
        self.compositionEditBox = QLineEdit(self)
        self.compositionEditBox.setReadOnly(True)
        subhbox.addWidget(self.compositionEditBox)
        self.qLineImmDict[self.compositionEditBox] = 'Composition'
        subvbox.addLayout(subhbox)
 
        subhbox = QHBoxLayout()
        label = QLabel('输入串显示为:', self)
        subhbox.addWidget(label)
        self.compDisplayEditBox = QLineEdit(self)
        self.compDisplayEditBox.setReadOnly(True)
        subhbox.addWidget(self.compDisplayEditBox)
        subvbox.addLayout(subhbox)  # 行---------------------
        self.qLineImmDict[self.compDisplayEditBox] = 'CompDisplay'
        hbox.addLayout(subvbox)

        subvbox = QVBoxLayout()
        label = QLabel('候选串', self)
        subvbox.addWidget(label)
        self.candList = QListWidget(self)
        subvbox.addWidget(self.candList)
        hbox.addLayout(subvbox)
        vbox.addLayout(hbox)

        hbox = QHBoxLayout()
        label = QLabel('在此输入:', self)
        hbox.addWidget(label)
        self.editorBox = QLineEdit4Ime(self.getIMM(), self)
        hbox.addWidget(self.editorBox)
        vbox.addLayout(hbox)  # 行---------------------

        vbox.addStretch(1)
        self.setLayout(vbox)

        self.show()

    def ImeKeyPressEvent(self):
        for k, v in self.qLineImmDict.items():
            if type(self.getIMM().GetCoreData(v)) == 'str':
                k.setText(self.getIMM().GetCoreData(v))
            else:
                k.setText(str(self.getIMM().GetCoreData(v)))
        self.candList.clear()
        for i in self.getIMM().GetCoreData('Candidates'):
            self.candList.addItem(i)
Пример #54
0
class TimelineWindow(QWidget):

    def __init__(self):
        super().__init__()
        timeline_bk_path = './source/pic/timeline_bk.png'
        hgzy_font_path = './source/font/HGZYT_CNKI.TTF'
        rem_ico_path = './source/pic/rem.png'
        fontId = QFontDatabase.addApplicationFont(hgzy_font_path)
        fontName = QFontDatabase.applicationFontFamilies(fontId)[0]
        self.index = -1
        self.pix = QPixmap(timeline_bk_path)
        self.resize(self.pix.width(),self.pix.height())
        self.pix = self.pix.scaled(int(self.pix.width()),int(self.pix.height()))
        self.setMask(self.pix.mask())
        screen = QDesktopWidget().screenGeometry()
        self.move((screen.width() - self.pix.width()) / 2, (screen.height() - self.pix.height()) / 2)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.FramelessWindowHint)
        rem_icon = QIcon(QPixmap(rem_ico_path))
        self.setWindowIcon(rem_icon)
        self.m_DragPosition = None
        self.m_drag = False
        self.animelist = QListWidget(self)
        self.animelist.setObjectName('AnimeList')
        self.animelist.setStyleSheet('#AnimeList{background:transparent}')
        self.animelist.setGeometry(200,165,310,350)
        self.animelist.setFont(QFont(fontName,11,QFont.Light))
        self.detail = Detail(self.x()+50,self.y()-15)
        self.detail_show = False
        self.animelist.itemDoubleClicked.connect(self.DetailBt)
        self.TimeLabels_path = []
        self.TimeLabels_clicked_path = []
        self.weekanime = TimeLine().get_week_anime()
        for time in range(1,8):
            self.TimeLabels_path.append('./source/pic/week_day_%d.png' % time)
            self.TimeLabels_clicked_path.append('./source/pic/week_day_%d_clicked.png' % time)
        self.TimeLabels = []
        for time in range(7):
            self.TimeLabels.append(QDlabel(self))
        self.setTimeLabel()
        self.daylabel = QLabel(self)
        self.daylabel.setObjectName('DayLabel')
        self.daylabel.setGeometry(290,110,200,40)
        self.daylabel.setFont(QFont(fontName,13,QFont.Bold))
        self.setDaytext()
        self.timelineshow = False

    def paintEvent(self, event):
        paint = QPainter(self)
        paint.drawPixmap(0,0,self.pix.width(),self.pix.height(),self.pix)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            if self.detail_show == True:
                self.detail.raise_()
            event.accept()
        elif event.button() == Qt.RightButton:
            if self.detail_show == True:
                self.detail.close()
                self.detail_show = False
            self.hide()
            self.timelineshow = False
            event.accept()

    def mouseMoveEvent(self, event):
        if Qt.LeftButton and self.m_drag:
            self.move(event.globalPos() - self.m_DragPosition)
            self.detail.move(self.x()+50 - self.detail.pix.width(),self.y()-15)
            event.accept()

    def mouseReleaseEvent(self, event):
        self.m_drag = False

    def closeEvent(self, event):
        self.detail.close()
        self.detail_show = False
        self.timelineshow = False

    def setTimeLabel(self):
        label_between = 60
        week_animes = self.weekanime
        start = week_animes[0]['day_of_week']-1
        for time in range(start,start+7):
            time_mod = time % 7
            self.TimeLabels[time_mod].setObjectName('DayLabel%d' % (time_mod+1))
            self.TimeLabels[time_mod].setStyleSheet('#DayLabel%d{border-image:url(%s)}' % (time_mod+1,self.TimeLabels_path[time_mod]))
            self.TimeLabels[time_mod].setGeometry(100,120 + label_between * (time-start),57,24)
        self.labelclick = week_animes[0]['day_of_week']
        self.TimeLabels[self.labelclick-1].setStyleSheet('#DayLabel%d{border-image:url(%s)}'
                                                         % (self.labelclick,self.TimeLabels_clicked_path[self.labelclick-1]))

    def setLabelClick(self, time_n):
        self.TimeLabels[self.labelclick-1].setStyleSheet(
            '#DayLabel%d{border-image:url(%s)}' % (self.labelclick, self.TimeLabels_path[self.labelclick-1]))
        self.TimeLabels[time_n].setStyleSheet('#DayLabel%d{border-image:url(%s)}'
                                                         % (time_n+1,self.TimeLabels_clicked_path[time_n]))

    def setDaytext(self):
        for animes in self.weekanime:
            if animes['day_of_week'] == self.labelclick:
                date = animes['date']
                day_of_week = self.labelclick
                self.animelist.clear()
                for anime in animes['seasons']:
                    item_text = ''
                    if anime['delay'] == 1:
                        item_text += anime['pub_time'] + ' ' + anime['delay_index'] + ' ' + anime['delay_reason'] + '\n' + anime['title']
                    else:
                        item_text += anime['pub_time'] + ' ' + anime['pub_index'] + '\n' + anime['title']
                    self.animelist.addItem(item_text)
                break
        week_day = ['周一','周二','周三','周四','周五','周六','周日']
        daytext = date + ' ' + week_day[day_of_week - 1]
        self.daylabel.setText(daytext)

    def GetDetail(self,title):
        dbsql = AnimeData()
        infos = dbsql.SqliteInfoSearch({'title':title})
        resinfo = []
        if infos:
            for info in infos:
                resinfo.append(info[0])
                resinfo.append(info[1])
                resinfo.append(info[2])
                resinfo.append(info[3])
                resinfo.append(info[4])
                resinfo.append(info[5])
                resinfo.append(info[6])
                resinfo.append(info[7])
        return resinfo

    def DelDetail(self):
        self.detail.animetitle.setParent(None)
        self.detail.animeintro.setParent(None)
        self.detail.animetags.setParent(None)
        self.detail.animeorder.setParent(None)
        self.detail.animeindexshow.setParent(None)
        self.detail.animeindexshowtext.setParent(None)
        self.detail.animetagstext.setParent(None)
        self.detail.animeordertext.setParent(None)
        self.detail.animetitletext.setParent(None)
        self.detail.animetagstext.setParent(None)
        self.detail.pic_label.setParent(None)

    def DetailBt(self):
        if self.detail_show == False:
            title = self.animelist.currentItem().text().split('\n')[1]
            info = self.GetDetail(title)
            self.detail.setInfo(info)
            self.index = self.animelist.currentIndex()
            self.detail.show()
            self.detail_show = True
        elif self.detail_show == True and self.index != self.animelist.currentIndex():
            self.detail.close()
            self.DelDetail()
            title = self.animelist.currentItem().text().split('\n')[1]
            info = self.GetDetail(title)
            self.index = self.animelist.currentIndex()
            self.detail.setInfo(info)
            self.detail.show()
        else:
            self.detail.close()
            self.DelDetail()
            self.index = -1
            self.detail_show = False
Пример #55
0
class Lookup(QWidget):
    MODEL_CLASS = None

    def __init__(self, parent, model):
        QWidget.__init__(self, parent, Qt.Window)
        self.model = model
        self.model.view = self
        self._setupUi()

        self.searchEdit.searchChanged.connect(self.searchChanged)
        self.searchEdit.returnPressed.connect(self.returnPressed)
        self.namesList.currentRowChanged.connect(self.currentRowChanged)
        self.namesList.itemDoubleClicked.connect(self.itemDoubleClicked)
        self._shortcutUp.activated.connect(self.upPressed)
        self._shortcutDown.activated.connect(self.downPressed)

    def _setupUi(self):
        self.setWindowTitle(tr("Lookup"))
        self.resize(314, 331)
        self.verticalLayout = QVBoxLayout(self)
        self.searchEdit = SearchEdit(self)
        self.verticalLayout.addWidget(self.searchEdit)
        self.namesList = QListWidget(self)
        self.namesList.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.namesList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.namesList.setUniformItemSizes(True)
        self.namesList.setSelectionRectVisible(True)
        self.verticalLayout.addWidget(self.namesList)

        self.searchEdit.immediate = True
        self._shortcutUp = QShortcut(self.searchEdit)
        self._shortcutUp.setKey(QKeySequence(Qt.Key_Up))
        self._shortcutUp.setContext(Qt.WidgetShortcut)
        self._shortcutDown = QShortcut(self.searchEdit)
        self._shortcutDown.setKey(QKeySequence(Qt.Key_Down))
        self._shortcutDown.setContext(Qt.WidgetShortcut)

    def _restoreSelection(self):
        self.namesList.setCurrentRow(self.model.selected_index)

    #--- Event Handlers
    def returnPressed(self):
        self.model.go()

    def searchChanged(self):
        self.model.search_query = str(self.searchEdit.text())

    def currentRowChanged(self, row):
        if row >= 0:
            self.model.selected_index = row

    def itemDoubleClicked(self, item):
        self.model.go()

    def upPressed(self):
        if self.namesList.currentRow() > 0:
            self.namesList.setCurrentRow(self.namesList.currentRow()-1)

    def downPressed(self):
        if self.namesList.currentRow() < self.namesList.count()-1:
            self.namesList.setCurrentRow(self.namesList.currentRow()+1)

    #--- model --> view
    def refresh(self):
        self.namesList.clear()
        self.namesList.addItems(self.model.names)
        self._restoreSelection()
        self.searchEdit.setText(self.model.search_query)

    def show(self):
        QWidget.show(self)
        self.searchEdit.setFocus()
        # see csv_options
        self.raise_()

    def hide(self):
        QWidget.hide(self)
Пример #56
0
class MainWindow(QMainWindow):
   
   # -------------------------------------------------------------------------- __init__()
   def __init__(self, parent=None):
      """ Main Window Constructor 
          This is a special case constructor as we need an object of type 
          QMainWindow to supprt a menu bar at the top of the window and a 
          status bar at the bottom of the window. However this QMAinWindow 
          widget has issues with adding additoonal widgets to it. We need 
          to create a main_widget within this QMainWindow object that can 
          easily have its own layout and have its own widgets assigend to 
          it. This main_widget will inherit from the generic QWidget.      """  
      
      super(MainWindow, self).__init__(parent)

      # Create and assign a main_widget and main_layout for the main window 
      self.main_widget = QWidget(self)
      self.main_layout = QGridLayout(self.main_widget)
      self.setCentralWidget(self.main_widget)

      # Define the test targets available. Test targets are folders in the 
      # test cases folder that hold individula test cases. 
      self.update_list_of_test_targets()  
      self.loaded_test_suite  = ""
      # self.loaded_test_target = ""
      self.loaded_target = ""
      self.test_case_full_pathname_list = []
      self.test_case_results = []

      self.pass_color    = QColor(100, 255, 100) # light green 
      self.fail_color    = QColor(255, 100, 100) # light red 
      self.running_color = QColor(255, 255, 100) # light yellow

      self.ready_icon     = ClickableQIcon( os.path.join(RESOURCE_PATH, "ready.png"   ) )
      self.running_icon   = ClickableQIcon( os.path.join(RESOURCE_PATH, "running.jpg" ) )
      self.passed_icon    = ClickableQIcon( os.path.join(RESOURCE_PATH, "passed.png"  ) )
      self.failed_icon    = ClickableQIcon( os.path.join(RESOURCE_PATH, "failed.jpg"  ) )
      self.not_ready_icon = ClickableQIcon( os.path.join(RESOURCE_PATH, "no.png"      ) )
      self.running_icon   = ClickableQIcon( os.path.join(RESOURCE_PATH, "running.jpg" ) )
      self.open_icon      = ClickableQIcon( os.path.join(RESOURCE_PATH, "open.png"    ) )
      self.exit_icon      = ClickableQIcon( os.path.join(RESOURCE_PATH, "exit.png"    ) )
      self.about_icon     = ClickableQIcon( os.path.join(RESOURCE_PATH, "about.png"   ) )
      self.help_icon      = ClickableQIcon( os.path.join(RESOURCE_PATH, "help.png"    ) )
      self.target_icon    = ClickableQIcon( os.path.join(RESOURCE_PATH, "target.png"  ) )

      # Each test suite result will be stored in a data time stamped folder 
      # so we are going to need a string to hold that value. Each time the 
      # run_test_suite() method is called we will get an updated value for 
      # this date_time_string
      self.date_time_string = time.strftime("%Y%m%d%H%M%S", time.localtime())

      # --- Define the frames for the main window / central widget in the main window. 
      #     The frames are the large division of the windows in which widgets are placed. 
      #     Here is the intended frame layout for the MainWindow: 
      #    +-----------------------------------------+
      #    |         Status and Summary Frame        |
      #    |-----------------------------------------|
      #    |         Test        |                   | 
      #    |     Suite Frame     |       Test        |
      #    |---------------------+       Case        |
      #    |       Console       |       Frame       |
      #    |        Frame        |                   |
      #    |                     |                   |
      #    +-----------------------------------------+
      self.status_frame  = QFrame()   # status and summary frame 
      self.suite_frame   = QFrame()   # test suite frame 
      self.case_frame    = QFrame()   # test case frame
      self.console_frame = QFrame()   # console frame  
      self.status_frame.setFrameStyle(  QFrame.Panel | QFrame.Raised ) # \
      self.suite_frame.setFrameStyle(   QFrame.Panel | QFrame.Raised ) #  \__ set initial frame styles
      self.case_frame.setFrameStyle(    QFrame.Panel | QFrame.Raised ) #  / 
      self.console_frame.setFrameStyle( QFrame.Panel | QFrame.Raised ) # / 
      # --- Add the frames to the grid layout of the main window
      #     to the main window
      #                         (     Frame,          Row, Col, RSpan, CSpan, Allignment )  
      self.main_layout.addWidget(self.status_frame,     0,   0,     5,    12) #, Qt.AlignLeft    | Qt.AlignTop)
      self.main_layout.addWidget(self.suite_frame,     13,   0,     8,     6) #, Qt.AlignHCenter | Qt.AlignTop)
      self.main_layout.addWidget(self.case_frame,       6,   6,    15,     6)
      self.main_layout.addWidget(self.console_frame,    6,   0,     7,     6)
      
      # Set the main_layout as the main_wigit
      self.main_widget.setLayout(self.main_layout)

      # --- Define and set the status bar that appears at the bottom of the wondow
      # TODO: make this font a little smaller 
      self.status_bar = self.statusBar()                  # Status Bar appears on the bottom  
      self.status_bar.showMessage('No Test Suite Loaded') # of the main window

      # --- Menu Bar for the top of the main window
      print("call create_menu_bar()")
      self.create_menu_bar()

      # --- Main Window Geometry 
      self.setGeometry(100, 100, 1200, 800)

      # --- Create the About Dialog 
      self.about_dialog = QDialog()
      self.about_dialog.setWindowTitle("About Test Master II")
      about_layout = QGridLayout()
      title        = QLabel("Test Mster II")
      author       = QLabel("Madvax")
      email        = QLabel("*****@*****.**")
      about_layout.addWidget(QLabel("---------------") , 1, 1 , Qt.AlignCenter)
      about_layout.addWidget(title                     , 2, 1 , Qt.AlignCenter)
      about_layout.addWidget(author                    , 3, 1 , Qt.AlignCenter)
      about_layout.addWidget(email                     , 4, 1 , Qt.AlignCenter)
      about_layout.addWidget(QLabel("---------------") , 5, 1 , Qt.AlignCenter)
      self.about_dialog.setLayout(about_layout)

      # --- Create the Help Dialog
      #     The help text in this dialog is taken from the HELP file
      #     in the root folder for this repository
      self.help_dialog = QDialog()
      self.help_dialog.setWindowTitle("Help With Test Master II")
      help_layout = QGridLayout()
      help_text = QTextEdit()
      try:
         f = open(os.path.join(MY_PATH, "../HELP")   , 'r')
         text = f.read()
         f.close()
         help_text.setText(text)
      except:
         help_text.setText("Sorry, Unlable to locate help file")   
      help_text.setReadOnly(True)
      font = help_text.font()
      font.setFamily("Currier")
      font.setPointSize(10)
      help_layout.addWidget(help_text, 0,0)
      self.help_dialog.setLayout(help_layout)
      self.help_dialog.setGeometry(150,150, 500,500)

      # ----------------------------------------------------------------------- Status Frame Widgets 
      # --- Create and populate the product pull down with products  
      #     taken from the test cases folder
           
      # --- Logo Image that loads the About Window
      self.logo = QPixmap(  os.path.join(RESOURCE_PATH, "splash.jpg")   )
      self.logo.scaled(10, 10, Qt.KeepAspectRatio)
      self.logo_image = ClickableQLabel()
      self.logo_image.setScaledContents(True)
      self.logo_image.setPixmap(self.logo)
      self.logo_image.setMaximumWidth(80)
      self.logo_image.setMaximumHeight(100)

      # --- Suite and Target labels
      self.test_suite_label  = QLabel("Test Suite: None")
      self.test_target_label = QLabel("Test Target: None")

      # --- Generic spacer to help with alignemtns 
      self.spacer = QLabel("   ")
      # --- Status Frame Layout and widget placement 
      status_frame_layout = QGridLayout()
      status_frame_layout.addWidget(self.logo_image        , 0, 0, 3, 1, Qt.AlignLeft | Qt.AlignTop     )
      status_frame_layout.addWidget(self.test_suite_label  , 1, 1, 1, 1, Qt.AlignLeft | Qt.AlignVCenter )
      status_frame_layout.addWidget(self.test_target_label , 0, 1, 1, 1, Qt.AlignLeft | Qt.AlignVCenter )
      status_frame_layout.addWidget(self.spacer            , 0, 4, 1, 1, Qt.AlignLeft | Qt.AlignTop     ) 
      status_frame_layout.addWidget(self.spacer            , 0, 5, 1, 3, Qt.AlignLeft | Qt.AlignTop     ) 
      self.status_frame.setLayout(status_frame_layout) 

      # ----------------------------------------------------------------------- SUITE FRAME WIDGETS
      palette = QPalette()
      palette.setColor(  QPalette.Text,  QColor(  0, 75,   0)   ) # Very Dark  green text on a 
      palette.setColor(  QPalette.Base,  QColor(200, 255, 200)   ) # very light green background
      text_area_font = QFont("Courier", 15, QFont.Bold)
      self.suite_text_area = QTextEdit()
      self.suite_text_area.setPalette(palette)
      self.suite_text_area.setFont(text_area_font)
      suite_layout = QVBoxLayout()
      suite_layout.addWidget(self.suite_text_area)
      self.suite_frame.setLayout(suite_layout)
      self.suite_text_area.setText("No Test Suite Loaded")

      # ----------------------------------------------------------------------- CONSOLE FRAME WIDGETS
      palette = QPalette()
      palette.setColor(QPalette.Text, Qt.white) # White text on a 
      palette.setColor(QPalette.Base, Qt.black) # black background
      text_area_font = QFont("Courier", 15, QFont.Bold)
      self.console_text_area = QTextEdit()
      self.console_text_area.setPalette(palette)
      self.console_text_area.setFont(text_area_font)
      console_layout = QVBoxLayout()
      console_layout.addWidget(self.console_text_area)
      self.console_frame.setLayout(console_layout)
      self.console_text_area.setText("Console Area")

      # ----------------------------------------------------------------------- TEST CASE FRAME WIDGETS 
      self.testcase_list_widget = QListWidget()
      self.testcase_list_widget.setLineWidth(3)
      testcase_layout = QVBoxLayout()
      testcase_layout.addWidget(self.testcase_list_widget)
      self.case_frame.setLayout(testcase_layout)   

   # -------------------------------------------------------------------------- create_menu_bar()
   def create_menu_bar(self):
      """ """
      # --- Create the menu bar object
      print("Crate Menu Bar") 
      menu_bar = self.menuBar()

      # --- Define some actions for the menu bar 
      open_action = QAction(QIcon(os.path.join(MY_PATH, '../res/open.png')), '&Open Test Suite', self)
      open_action.setShortcut('Ctrl+O')
      open_action.setStatusTip('Open a Test Suite')
      open_action.triggered.connect( self.open_test_suite)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      exit_action = QAction(QIcon(os.path.join(MY_PATH, '../res/exit.png')), '&Exit', self)
      exit_action.setShortcut('Ctrl+Q')
      exit_action.setStatusTip('Exit application')
      exit_action.triggered.connect( qApp.quit)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      select_target_action = QAction(QIcon(os.path.join(MY_PATH, '../res/target.png')), '&Target', self)
      select_target_action.setShortcut('Ctrl+T')
      select_target_action.setStatusTip('Select test taget')
      select_target_action.triggered.connect( self.select_target)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      run_tests_action = QAction(QIcon(os.path.join(MY_PATH, '../res/run.png')), '&Run Test', self)
      run_tests_action.setShortcut('Ctrl+R')
      run_tests_action.setStatusTip('Run tests agains the target')
      run_tests_action.triggered.connect( self.run_test_suite)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      stop_tests_action = QAction(QIcon(os.path.join(MY_PATH, '../res/stop.png')), '&Stop Test', self)
      stop_tests_action.setShortcut('Ctrl+S')
      stop_tests_action.setStatusTip('Stops running tests')
      stop_tests_action.triggered.connect( self.open_test_suite)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      help_action = QAction(QIcon(os.path.join(MY_PATH, '../res/help.png')), '&Help', self)
      help_action.setShortcut('Ctrl+H')
      help_action.setStatusTip('Help')
      help_action.triggered.connect( self.open_help)
      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      about_action = QAction(QIcon(os.path.join(MY_PATH, '../res/about.png')), '&About', self)
      about_action.setShortcut('Ctrl+A')
      about_action.setStatusTip('About Test MAster II')
      about_action.triggered.connect( self.open_about)

      # Add actions to the menu bar 
      fileMenu = menu_bar.addMenu('&File')
      testMenu = menu_bar.addMenu('&Test')
      helpMenu = menu_bar.addMenu('&Help')
      # - - - - - - - - - - - - - - - - - - -
      fileMenu.addAction(open_action)    
      fileMenu.addAction(exit_action)
      # - - - - - - - - - - - - - - - - - - -
      testMenu.addAction(select_target_action)
      testMenu.addAction(run_tests_action)
      testMenu.addAction(stop_tests_action)
      # - - - - - - - - - - - - - - - - - - -
      helpMenu.addAction(help_action)
      helpMenu.addAction(about_action)

   # -------------------------------------------------------------------------- open_test_suite() 
   def open_test_suite(self):
      """ Open a test suite file and loads the test cases from the suite into the tool.
          There is a chained process flow when you open a test suite:
             open_test_suite() calls select_target() 
             select_target then calls load_test_cases() 
          Once a test suite is opened, the user may later choose a new target for the same 
          test suite as teh select_target() method call load_test_cases().      """ 
      
      self.test_case_data_list = []
      url = QUrl()                                    # This File Dialog should start in  
      url.setScheme("file")                           # the test suites folder by default. 
      url.setPath(   "%s/../testsuites" %MY_PATH   )  # TODO: os.path.join()
      options = QFileDialog.Options()
      options |= QFileDialog.DontUseNativeDialog
      file_dialog = QFileDialog()
      file_dialog.setDirectoryUrl(url)
      self.testsuite_file, _ = file_dialog.getOpenFileName(self,"QFileDialog.getOpenFileName()", "","All Files (*)", options=options)
      if self.testsuite_file:
         self.test_suite_label.setText("Test Suite: %s" %self.testsuite_file.split('/')[LAST])
         message = "Loaded Test Suite:  %s" %self.testsuite_file 
         logger.info(message)
         # Crate a list of test cases from the test suite file. However, these 
         # test cases are only file names with not path. We'll have to add the path 
         # based on the target selected.   
         try:
            f = open(self.testsuite_file, 'r')
            lines = f.readlines()
            f.close()
            self.suite_text_area.clear()
            for line in lines:
               line = line.strip()
               self.suite_text_area.append(line)
         except:
            message = "Unalbe to read test cases from test suite %s" %self.testsuite_file
            logger.error(message)
            self.suite_text_area.setText(message) 
            lines = []

         self.test_case_file_list = [] # a list of test case file names with no paths
         for line in lines:
            line = line.strip()
            if len(line) < 1:
               pass
            elif line.startswith('#'):
               pass
            else:
               self.test_case_file_list.append(line)     

         self.test_case_count = len(self.test_case_file_list)
         message = "Found %d test cases in %s" %(self.test_case_count, self.testsuite_file.split('/')[LAST])
         logger.info(message)
         self.status_bar.showMessage(message)  

         # open the select a test target for this suite
         self.select_target()  

         # load the test cases 
         # logger.info("Back from select_target() ... calling load_test_cases()")
         # self.load_test_cases()

   # -------------------------------------------------------------------------- load_test_cases()
   def load_test_cases(self):
      """ When we load the test cases from the test suite file we populate the 
          test case frame a.k.a. cases frame with the test cases. However, 
          before we put up the green run icon we have to ensure that a target 
          as been selected and using that target, verify that the test cases 
          requested in the test suite are available in the target folder.    """
      self.test_cases = []                # Start with an empty list of test cases 
      self.testcase_list_widget.clear()   # Clear any test cases from the test case frame 
      self.testcase_list_widget_items_list = []
      
      if len(self.test_case_file_list) > 0:
         
         counter = 0 
 
         for t in self.test_case_file_list:
 
            counter += 1
            logger.info("Loading test case %d of %d %s" %(counter, len(self.test_case_file_list), t) )

            # In this loop the variable t is the file name of a candidate test case 
            # without the path of the file. We will need to use the target to 
            # generate a ful path file name for the test case in this loop.
            # 
            # Create a list of test case data where each item in the list is a 
            # dictionary with two key-valie pairs: name an state. The name is 
            # the file name of the script as read from the test suite file and 
            # the state is one of: 
            #       "not ready" - File not found or target not specified 
            #       "ready"     - File exists and target is specified
            #       "running"   - Test case is being execuited
            #       "passed"    - Test case has finished without error or failed step
            #       "failed"    - Test case failed one or more steps 
            #       "error"     - Test case finished with and error, not the same as a failure 

            # Definethe full path of the candidate test case 
            test_case_path_filename = ""
            test_case_path_filename =  os.path.join(  os.path.join(TESTCASE_PATH, self.loaded_target), t  )
            message = "Test case full path %s" %(test_case_path_filename) 
            logger.info(message)

            test_case_record = {} # used to hold the data for a test case 

            # if the full path test case file exists then we mark it a ready
            # otherwise we mark it a not ready  
            if os.path.isfile( test_case_path_filename  ):
               test_case_record = {"name": t, "state":ready, "file": test_case_path_filename}   
               #                                                                 # \  ***    This is the list of    ***
               self.test_case_full_pathname_list.append(test_case_path_filename) #  > ***   executable test cases   ***
               #                                                                 # /  *** used for "run test suite" *** 
            else: 
               test_case_record = {"name": t, "state":not_ready, "file": None}   
             
            # define the icon for the test case based on the state of the test case 
            if test_case_record["state"] == ready:  
               test_case_icon = ClickableQIcon(  os.path.join(RESOURCE_PATH, "run.png")  )
            else:   
               test_case_icon = ClickableQIcon(  os.path.join(RESOURCE_PATH, "no.png")  )
            test_case_record["icon"] = test_case_icon

            # At this point the test case reacod is a dictionary with the key-value
            # paris listed below:
            # {"same": string, "state", string, "file": full_path_filename, "icon": ClickableIcon}
            # uisng this date we can create a QListItem and add it to the testcase_list_widget. 
            message = "Adding test case %s to the test case list widget" %test_case_record["name"]
            logger.info(message)
            list_item = QListWidgetItem()
            list_item.setText("Name: %s\nFile:%s\nState:%s" %(test_case_record["name"], test_case_record["file"], test_case_record["state"]))
            list_item.setIcon(test_case_record["icon"])
            self.testcase_list_widget.addItem(list_item)
            self.testcase_list_widget_items_list.append(list_item)
      else:
         message = "Failed to load any test cases from %s" %self.testsuite_file.split('/')[LAST] 
         logger.warning(message) 
         self.status_bar.showMessage(message)   
  
   # -------------------------------------------------------------------------- update_list_of_test_targets()
   def update_list_of_test_targets(self):
      """ update the list of test targets from the contents of the testcases folder """
      target_candidates = os.listdir(TESTCASE_PATH)
      self.target_list = [{"name":"Not selected",  "folder":"Not selected" }]
      for item in target_candidates:
         if os.path.isdir(  os.path.join(TESTCASE_PATH, item)   ):
            target = {}
            target["name"] = item
            target["folder"] = os.path.join(TESTCASE_PATH, item)
            self.target_list.append(target)
            logger.info("Added target %s to the list of targets" %item)  

   # -------------------------------------------------------------------------- select_target()
   def select_target(self):
      """ Select a target from teh list of available test targets """ 
      self.update_list_of_test_targets()
      targets = []
      for target in self.target_list[1:]:
         targets.append(target["name"])
      item, okPressed = QInputDialog.getItem(self, "Select Test Target","Target:", targets, 0, False)
      if okPressed and item:
         self.test_target_label.setText("Test Target: %s" %item)
         self.loaded_target = item
         logger.info("Loaded Test Target: %s" %item)   
         
         # load the test cases 
         logger.info("Back from select_target() ... calling load_test_cases()")
         self.load_test_cases()

   # -------------------------------------------------------------------------- run_test_suite()
   def run_test_suite(self):
      """ Execute all of the tests in a test suite. The list of executables is 
          stored in self.test_case_full_pathname_list. """ 
          
      if len(self.test_case_full_pathname_list) > 0:

         self.suite_results_folder = os.path.join(RESULTS_HOME, time.strftime("%Y%m%d%H%M%S", time.localtime())   )
         os.mkdir(self.suite_results_folder)
         message = "Created suite results folder %s" %self.suite_results_folder
         logger.info(message)

         # intiialize a list of dictionaries to store the results of this test suite run
         self.test_suite_results = []  

         # This is the main loop for executing test cases.
         # In this loop we create folders for the results 
         # of each test case and call/run each test cases
         # and provide the test cases results folder name 
         # as the last argument to the test case invocation
         # command. We also keep track of the test case 
         # results and store them in the test case list: 
         #  self.test_case_results   
         counter = 0
         for test_case in self.test_case_full_pathname_list:
         
            test_case_results = {}
            self.active_test_case = test_case
            self.active_test_case_results_folder = ""

            counter += 1  

            # Make the test case results folder
            test_case_short_name = test_case.split('/')[LAST]   
            if '.' in test_case_short_name:
               test_case_short_name = test_case_short_name.split('.')[FIRST]
            test_case_results_folder = os.path.join(self.suite_results_folder, test_case_short_name)
            os.mkdir(test_case_results_folder)
            self.active_test_case_results_folder = test_case_results_folder
            message = "Created test case resulst folder %s" %test_case_results_folder
            logger.info(message)

            # Identify and use the test case list widget item for this test case 
            list_item  = self.testcase_list_widget_items_list[counter - 1]
            bg_color   = self.running_color
            icon       = self.running_icon
            text       = "Test: %s\nFile: %s\nState: Running" %(test_case.split('/')[LAST], test_case, )
            self.set_test_case_list_wdiget_item(list_item, icon, bg_color, text )
            message = "Running Test case %d of %d: %s " %(counter, len(self.test_case_full_pathname_list), test_case)
            logger.info(message)
            self.status_bar.showMessage(message)

            self.repaint() # heavy sigh ...

            # *************************
            # *** RUN THE TEST CASE ***
            # *************************
            results = self.execute_test_case()
            if results["return_code"] == 0:
               list_item  = self.testcase_list_widget_items_list[counter - 1]
               bg_color   = self.pass_color
               icon       = self.passed_icon
               text       = "Test: %s\nFile: %s\nState: PASSED" %(test_case.split('/')[LAST], test_case, )
               self.set_test_case_list_wdiget_item(list_item, icon, bg_color, text )
               test_case_results = {"testcase"       : test_case_short_name, 
                                    "file"           : test_case, 
                                    "result"         : "passed", 
                                    "results_folder" : test_case_results_folder }
            else:
               list_item  = self.testcase_list_widget_items_list[counter - 1]
               bg_color   = self.fail_color
               icon       = self.failed_icon
               text       = "Test: %s\nFile: %s\nState: FAIILED" %(test_case.split('/')[LAST], test_case, )
               self.set_test_case_list_wdiget_item(list_item, icon, bg_color, text )
               test_case_results = {"testcase"       : test_case_short_name, 
                                    "file"           : test_case, 
                                    "result"         : "failed", 
                                    "results_folder" : test_case_results_folder }
            self.repaint()

            # Write the output and errors files to the test case results folder 
            # output  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            tc_output = results["output"]
            tc_output = tc_output.strip()
            if len(tc_output) < 1:
               pass
            else:
               output_file = os.path.join(test_case_results_folder, TC_OUTPUT_FILE) 
               try:
                  f = open(output_file, 'w')
                  f.write(tc_output)
                  f.close()
               except Exception as e:
                  message = "Ubnable to write to test case output file %s" %output_file
                  logger.error(message)
            # errors  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            tc_errors = results["error"]
            tc_errors = tc_errors.strip()
            if len(tc_errors) < 1:
               pass
            else:
               errors_file = os.path.join(test_case_results_folder, TC_ERRORS_FILE) 
               try:
                  f = open(errors_file, 'w')
                  f.write(tc_errors)
                  f.close()
               except Exception as e:
                  message = "Ubnable to write to test case errors file %s" %errors_file
                  logger.error(message)

            # Test Suite results can be used later in summary reports or general reporting   
            self.test_suite_results.append(test_case_results)

            message = "test case %d of %d complete" %(counter, len(self.test_case_full_pathname_list))
            self.status_bar.showMessage(message)
            logger.info(message)
            # Need a method for updateing all of the attributes of a list item 
         
         # Log the results
         logger.info("Test suite results:")
         logger.info(str(self.test_suite_results)) 

      else:
         message = "No test cases loaded. Nothing to do"
         logger.warning(message)
         mBox = QMessageBox()
         mBox.setText(message)
         mBox.setWindowTitle("Warning -- No test cases")
         mBox.setIcon(QMessageBox.Warning)
         mBox.setStandardButtons(QMessageBox.Ok)
         mBox.exec_()

   # -------------------------------------------------------------------------- set_test_case_list_wdiget_item()
   def set_test_case_list_wdiget_item(self, list_widget_item, icon , background_color, text ):
      """ sets the properties of a test cacse list widget item
             list_widget_item : test case list widget item 
             icon             : QIcon or ClickableIcon 
             background_color : Qt.QColor 
             text             : test for the list idget item  
          """
      list_widget_item.setText(text)
      list_widget_item.setBackground(background_color)
      list_widget_item.setIcon(icon)


   # -------------------------------------------------------------------------- open_about() 
   def open_about(self):
      """ """
      self.about_dialog.exec()

   # -------------------------------------------------------------------------- open_help() 
   def open_help(self):
      """ """
      self.help_dialog.exec()

   # -------------------------------------------------------------------------- execute_test_case()
   def execute_test_case(self):
      """ """

      # If the active test case is a python script then be sure to run it 
      # UNBUFFERED mode otehrwise just execute the active test case 
      if self.active_test_case.endswith('.py') or self.active_test_case.endswith('.Py') or self.active_test_case.endswith('.PY') :
         command_list = [PYTHON_INTERPRETER, "-u", self.active_test_case]
      else:
         command_list = [self.active_test_case]
      message = "RUNING:\n%s\n\nRESULTS IN:\n%s\n\n" %(self.active_test_case, self.active_test_case_results_folder)
      logger.info(message)   

      p = subprocess.Popen(command_list           , 
                           stdout=subprocess.PIPE ,
                           stderr=subprocess.PIPE )

      output_buffer  = ""
      error_buffer   = ""
      return_code    = 127

      sel = selectors.DefaultSelector()
      sel.register(p.stdout, selectors.EVENT_READ)
      sel.register(p.stderr, selectors.EVENT_READ)
      
      while p.poll() == None:
         for key, _ in sel.select():
            
            data = key.fileobj.read1().decode()
            if not data:
               break
            if key.fileobj is p.stdout:
               output_buffer += data             
            else:
               error_buffer += data   

            data = "%s" %str(data).strip()
            # text_buffer += data
            self.console_text_area.append(data)
            self.console_text_area.moveCursor(QTextCursor.End)
            self.repaint()   
   
      return {"return_code": p.poll()      ,
              "output"     : output_buffer ,
              "error"      : error_buffer  }   

   # -------------------------------------------------------------------------- event()
   def event(self, e):
      """ Manages the default text of the status bar """
      default_text = "By your command"
      if e.type() == QEvent.StatusTip:
         if e.tip() == '':
            e = QStatusTipEvent(default_text)  
      return super().event(e)
Пример #57
0
class PostProcessor(QMainWindow):

    sim_results_changed = pyqtSignal()
    post_results_changed = pyqtSignal()

    figures_changed = pyqtSignal(list, str)

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self._settings = QSettings()
        self._logger = logging.getLogger(self.__class__.__name__)

        self.setWindowTitle("Processing")
        self.setWindowIcon(QIcon(get_resource("processing.png")))
        self.mainFrame = QWidget(self)
        self.resize(1000, 600)

        # toolbar
        self.toolBar = QToolBar("file control")
        self.toolBar.setIconSize(QSize(24, 24))
        self.addToolBar(self.toolBar)

        self.actLoad = QAction(self)
        self.actLoad.setText("load result file")
        self.actLoad.setIcon(QIcon(get_resource("load.png")))
        self.actLoad.setDisabled(False)
        self.actLoad.triggered.connect(self.load_result_files)

        self.actPostLoad = QAction(self)
        self.actPostLoad.setText("load post-result file")
        self.actPostLoad.setIcon(QIcon(get_resource("load.png")))
        self.actPostLoad.setDisabled(False)
        self.actPostLoad.triggered.connect(self.load_post_result_files)

        self.actSwitch = QAction(self)
        self.actSwitch.setText("switch display mode")
        self.actSwitch.setIcon(QIcon(get_resource("left_mode.png")))
        self.actSwitch.setDisabled(False)
        self.actSwitch.triggered.connect(self.switch_sides)
        self.displayLeft = True

        self.spacer1 = QWidget()
        self.spacer2 = QWidget()
        self.spacer1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.spacer2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.actReloadMethods = QAction(self)
        self.actReloadMethods.setText("reload methods")
        self.actReloadMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMethods.setDisabled(False)
        self.actReloadMethods.triggered.connect(self.update_post_method_list)

        self.actReloadMetaMethods = QAction(self)
        self.actReloadMetaMethods.setText("reload meta methods")
        self.actReloadMetaMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMetaMethods.setDisabled(False)
        self.actReloadMetaMethods.triggered.connect(
            self.update_meta_method_list)
        
        self.toolBar.addAction(self.actLoad)
        self.toolBar.addAction(self.actReloadMethods)
        
        self.toolBar.addWidget(self.spacer1)
        self.toolBar.addAction(self.actSwitch)
        self.toolBar.addWidget(self.spacer2)

        self.toolBar.addAction(self.actReloadMetaMethods)
        self.toolBar.addAction(self.actPostLoad)

        # main window
        self.grid = QGridLayout(self.mainFrame)
        self.grid.setColumnMinimumWidth(0, 70)
        self.grid.setColumnStretch(0, 0)
        self.grid.setColumnStretch(1, 1)

        self.methodList = QListWidget(self)
        self.methodList.itemDoubleClicked.connect(
            self.post_processor_clicked)
        self.update_post_method_list()
        self.metaMethodList = QListWidget(self)
        self.metaMethodList.itemDoubleClicked.connect(
            self.meta_processor_clicked)
        self.update_meta_method_list()

        self.sim_result_list = QListWidget(self)
        self.sim_results_changed.connect(self.update_result_list)
        self.results = []

        self.delShort = QShortcut(QKeySequence(Qt.Key_Delete),
                                  self.sim_result_list)
        self.delShort.activated.connect(self.remove_result_item)

        # figures
        self._figure_dict = {}
        self.figures_changed.connect(self.update_figure_lists)

        self.post_figure_list = QListWidget(self)
        self.post_figure_list.currentItemChanged.connect(
            self.current_figure_changed)
        self.meta_figure_list = QListWidget(self)
        self.meta_figure_list.currentItemChanged.connect(
            self.current_figure_changed)

        self.plotView = QWidget()
        self.lastFigure = None

        self.post_result_list = QListWidget(self)
        self.post_results_changed.connect(self.update_post_result_list)
        self.post_results = []
        self.delShortPost = QShortcut(QKeySequence(Qt.Key_Backspace),
                                      self.post_result_list)
        self.delShortPost.activated.connect(self.remove_post_result_item)

        # log dock
        self.logBox = QPlainTextEdit(self)
        self.logBox.setReadOnly(True)

        # init logger for logging box
        self.textLogger = PlainTextLogger(logging.INFO)
        self.textLogger.set_target_cb(self.logBox.appendPlainText)
        logging.getLogger().addHandler(self.textLogger)

        self.grid.addWidget(QLabel("Result Files:"), 0, 0)
        self.grid.addWidget(self.sim_result_list, 1, 0)
        self.grid.addWidget(QLabel("Postprocessors:"), 2, 0)
        self.grid.addWidget(self.methodList, 3, 0)
        self.grid.addWidget(QLabel("Figures:"), 4, 0)
        self.grid.addWidget(self.post_figure_list, 5, 0)
        self.grid.addWidget(QLabel("Selected Figure:"), 0, 1)
        self.grid.addWidget(QLabel("Postprocessor Files:"), 0, 2)
        self.grid.addWidget(self.post_result_list, 1, 2)
        self.grid.addWidget(QLabel("Metaprocessors:"), 2, 2)
        self.grid.addWidget(self.metaMethodList, 3, 2)
        self.grid.addWidget(QLabel("Figures:"), 4, 2)
        self.grid.addWidget(self.meta_figure_list, 5, 2)
        self.grid.addWidget(self.logBox, 6, 0, 1, 3)

        self.mainFrame.setLayout(self.grid)
        self.setCentralWidget(self.mainFrame)

        # status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

    def load_result_files(self):
        path = self._settings.value("path/simulation_results")

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setDirectory(path)
        dialog.setNameFilter("PyMoskito Result files (*.pmr)")

        if dialog.exec_():
            files = dialog.selectedFiles()
            for single_file in files:
                if single_file:
                    self._load_result_file(single_file)

    def _load_result_file(self, file_name):
        """
        loads a result file
        """
        self._logger.info("loading result file {}".format(file_name))
        with open(file_name.encode(), "rb") as f:
            self.results.append(pickle.load(f))

        self.sim_results_changed.emit()

    def update_result_list(self):
        self.sim_result_list.clear()
        for res in self.results:
            name = res["regime name"]
            self.sim_result_list.addItem(name)

    def remove_result_item(self):
        if self.sim_result_list.currentRow() >= 0:
            del self.results[self.sim_result_list.currentRow()]
            self.sim_result_list.takeItem(self.sim_result_list.currentRow())

    def load_post_result_files(self):
        path = self._settings.value("path/processing_results")

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setDirectory(path)
        dialog.setNameFilter("Postprocessing Output files (*.pof)")

        if dialog.exec_():
            files = dialog.selectedFiles()
            for single_file in files:
                if single_file:
                    self._load_post_result_file(single_file)

    def _load_post_result_file(self, file_name):
        """
        loads a post-result file (.pof)
        """
        name = os.path.split(file_name)[-1][:-4]
        self._logger.info("loading result file {}".format(file_name))
        with open(file_name.encode(), "rb") as f:
            results = pickle.load(f)
            results.update({"name": name})
            self.post_results.append(results)

        self.post_results_changed.emit()

    def update_post_result_list(self):
        self.post_result_list.clear()
        for res in self.post_results:
            name = res["name"]
            self.post_result_list.addItem(name)

    def remove_post_result_item(self):
        if self.post_result_list.currentRow() >= 0:
            del self.post_results[self.post_result_list.currentRow()]
            self.post_result_list.takeItem(self.post_result_list.currentRow())

    def update_post_method_list(self):
        self.methodList.clear()
        modules = pm.get_registered_processing_modules(PostProcessingModule)
        for mod in modules:
            self.methodList.addItem(mod[1])

    def update_meta_method_list(self):
        self.metaMethodList.clear()
        modules = pm.get_registered_processing_modules(MetaProcessingModule)
        for mod in modules:
            self.metaMethodList.addItem(mod[1])

    def post_processor_clicked(self, item):
        self.run_processor(str(item.text()), "post")

    def meta_processor_clicked(self, item):
        self.run_processor(str(item.text()), "meta")

    def run_processor(self, name, processor_type):
        if processor_type == "post":
            result_files = self.results
            base_cls = PostProcessingModule
        elif processor_type == "meta":
            result_files = self.post_results
            base_cls = MetaProcessingModule
        else:
            self._logger.error("unknown processor type {0}".format(
                processor_type))
            raise ValueError("unknown processor type {0}".format(
                processor_type))

        if not result_files:
            self._logger.warning("run_processor() Error: no result file loaded")
            return

        processor_cls = pm.get_processing_module_class_by_name(base_cls, name)
        processor = processor_cls()

        figs = []
        try:
            self._logger.info("executing processor '{0}'".format(name))
            figs = processor.process(result_files)
        except Exception as err:
            self._logger.exception("Error in processor")

        self.figures_changed.emit(figs, processor_type)
        self._logger.info("finished postprocessing")

    def update_figure_lists(self, figures, target_type):
        # remove no longer needed elements
        for item, fig in [(key, val[0])
                          for key, val in self._figure_dict.items()
                          if val[1] == target_type]:
            if fig not in [new_fig["figure"] for new_fig in figures]:
                if target_type == "post":
                    old_item = self.post_figure_list.takeItem(
                        self.post_figure_list.row(item))
                    del old_item
                elif target_type == "meta":
                    old_item = self.meta_figure_list.takeItem(
                        self.meta_figure_list.row(item))
                    del old_item

                del self._figure_dict[item]

        # add new ones to internal storage
        for fig in figures:
            if fig["figure"] not in self._figure_dict.values():
                new_entry = [(fig["name"],
                              (QListWidgetItem(fig["name"]),
                               fig["figure"], target_type)
                              )]
                self._figure_dict.update(new_entry)

        # add to display
        for key, val in self._figure_dict.items():
            if val[2] == "post":
                self.post_figure_list.addItem(val[0])
            elif val[2] == "meta":
                self.meta_figure_list.addItem(val[0])

        self.post_figure_list.setCurrentItem(self.post_figure_list.item(0))
        self.meta_figure_list.setCurrentItem(self.meta_figure_list.item(0))

    def current_figure_changed(self, current_item, last_item=None):
        if current_item is None:
            return

        figures = self._figure_dict

        if self.lastFigure:
            self.grid.removeWidget(self.lastFigure)
            self.lastFigure.setVisible(False)

        if current_item.text() in figures:
            figure_widget = figures[current_item.text()][1]
            self.grid.addWidget(figure_widget, 1, 1, 5, 1)
            figure_widget.setVisible(True)
            self.lastFigure = figure_widget
        
    def switch_sides(self):
        self.displayLeft = not self.displayLeft
        if self.displayLeft:
            self.actSwitch.setIcon(QIcon(get_resource("left_mode.png")))
            self.post_figure_list.setFocus()
            self.current_figure_changed(self.post_figure_list.currentItem())
        else:
            self.actSwitch.setIcon(QIcon(get_resource("right_mode.png")))
            self.meta_figure_list.setFocus()
            self.current_figure_changed(self.meta_figure_list.currentItem())
Пример #58
0
class MovieListWidget(GuiComponent):
    def __init__(self, parent=None):
        """
        This widget displays a list of film

        :param parent: parent of the widget
        :type parent: QWidget

        """
        super(MovieListWidget, self).__init__(parent)

        self.createWidgets()
        self.updateWidgets(Movie.query())

    def onShowFrame(self):
        self.emit(ShowSearch())

    def createWidgets(self):
        grid = QGridLayout(self)
        self.lstWidgets = QListWidget(self)

        self.lblNoFilm = QLabel("There is no film")
        font = QFont('', 15)
        self.lblNoFilm.setFont(font)
        grid.addWidget(self.lblNoFilm, 0, 0, 1, 1, Qt.Qt.AlignCenter)
        grid.addWidget(self.lstWidgets, 0, 0)
        self.setLayout(grid)

    def updateWidgets(self, data):
        """
        update the list with the data parameter
        :param data:
        :type: list of movies model
        :return:
        """
        hasFilm = False
        self.lstWidgets.clear()

        for film in data:
            hasFilm = True
            try:
                item = QListWidgetItem(self.lstWidgets)
                itemW = ResultRow(self, film)
                item.setSizeHint(itemW.sizeHint())
                self.lstWidgets.setItemWidget(item, itemW)
                #itemW.show.connect(lambda x: self.clickedSee(film))
                itemW.btnSee.clicked.connect(
                    lambda ignore, f=film: self.clickedSee(f))

            except Exception as e:
                log.info("ERROR WHILE UPDATING MOVIE LIST")
                log.info(e)
        if hasFilm is True:
            self.lblNoFilm.setVisible(False)
        else:
            self.lblNoFilm.setVisible(True)
            self.lblNoFilm.setText("There is no result for this research")

        if Movie.query().count() == 0:
            self.lblNoFilm.setVisible(True)
            self.lblNoFilm.setText(
                "No film in database, please add a folder (File - add folder)")
        log.info("List of widgets %s", len(self.lstWidgets))

    def clickedSee(self, film):
        self.emit(ShowFrame(MovieWidget.__name__, film))

    def handle(self, event):
        super().handle(event)  #remember kids, always call super
        if isinstance(event, Response) and isinstance(event.request,
                                                      SearchRequest):
            log.info("-------------- UPDATING LIST OF MOVIES ----------------")
            self.updateWidgets(event.data)
            event.stopPropagate()
            #self.emit(ShowFrame(self))
        if isinstance(
                event, ShowFrame
        ) and event.frame == self.__class__.__name__ and event.data is not None:
            self.updateWidgets(event.data)
Пример #59
0
class ListEdit(QWidget):
    """A widget to edit a list of items (e.g. a list of directories)."""
    
    # emitted when anything changed in the listbox.
    changed = pyqtSignal()
    
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        layout = QGridLayout(self)
        self.setLayout(layout)
        
        self.addButton = QPushButton(icons.get('list-add'), '')
        self.editButton = QPushButton(icons.get('document-edit'), '')
        self.removeButton = QPushButton(icons.get('list-remove'), '')
        self.listBox = QListWidget()
        
        layout.setContentsMargins(1, 1, 1, 1)
        layout.setSpacing(0)
        layout.addWidget(self.listBox, 0, 0, 8, 1)
        layout.addWidget(self.addButton, 0, 1)
        layout.addWidget(self.editButton, 1, 1)
        layout.addWidget(self.removeButton, 2, 1)
        
        @self.addButton.clicked.connect
        def addClicked():
            item = self.createItem()
            if self.openEditor(item):
                self.addItem(item)
                
        @self.editButton.clicked.connect
        def editClicked():
            item = self.listBox.currentItem()
            item and self.editItem(item)
        
        @self.removeButton.clicked.connect
        def removeClicked():
            item = self.listBox.currentItem()
            if item:
                self.removeItem(item)
        
        @self.listBox.itemDoubleClicked.connect
        def itemDoubleClicked(item):
            item and self.editItem(item)
            
        self.listBox.model().layoutChanged.connect(self.changed)
    
        def updateSelection():
            selected = bool(self.listBox.currentItem())
            self.editButton.setEnabled(selected)
            self.removeButton.setEnabled(selected)
        
        self.changed.connect(updateSelection)
        self.listBox.itemSelectionChanged.connect(updateSelection)
        updateSelection()
        app.translateUI(self)
    
    def translateUI(self):
        self.addButton.setText(_("&Add..."))
        self.editButton.setText(_("&Edit..."))
        self.removeButton.setText(_("&Remove"))
    
    def createItem(self):
        return QListWidgetItem()
        
    def addItem(self, item):
        self.listBox.addItem(item)
        self.itemChanged(item)
        self.changed.emit()
        
    def removeItem(self, item):
        self.listBox.takeItem(self.listBox.row(item))
        self.changed.emit()
        
    def editItem(self, item):
        if self.openEditor(item):
            self.itemChanged(item)
            self.changed.emit()
            
    def setCurrentItem(self, item):
        self.listBox.setCurrentItem(item)
        
    def setCurrentRow(self, row):
        self.listBox.setCurrentRow(row)
        
    def openEditor(self, item):
        """Opens an editor (dialog) for the item.
        
        Returns True if the dialog was accepted and the item edited.
        Returns False if the dialog was cancelled (the item must be left
        unedited).
        """
        pass
    
    def itemChanged(self, item):
        """Called after an item has been added or edited.
        
        Re-implement to do something at this moment if needed, e.g. alter the
        text or display of other items.
        """
        pass
    
    def setValue(self, strings):
        """Sets the listbox to a list of strings."""
        self.listBox.clear()
        self.listBox.addItems(strings)
        self.changed.emit()
        
    def value(self):
        """Returns the list of paths in the listbox."""
        return [self.listBox.item(i).text()
            for i in range(self.listBox.count())]
    
    def setItems(self, items):
        """Sets the listbox to a list of items."""
        self.listBox.clear()
        for item in items:
            self.listBox.addItem(item)
            self.itemChanged(item)
        self.changed.emit()
    
    def items(self):
        """Returns the list of items in the listbox."""
        return [self.listBox.item(i)
            for i in range(self.listBox.count())]
        
    def clear(self):
        """Clears the listbox."""
        self.listBox.clear()
        self.changed.emit()
Пример #60
0
class MainWidget(QWidget):
    def __init__(self, parent=None):

        super().__init__()
        self.parent = parent

        self.template = None
        self.characters = []
        self.charIndex = 0

        self.init_UI()

    def connect_all(self):

        self.addChar.clicked.connect(self.add_character)
        self.removeChar.clicked.connect(self.remove_character)

        self.listWidget.currentItemChanged.connect(self.item_changed)
        self.listWidget.itemChanged.connect(self.item_text_changed)

        for r in range(self.tabs.count()):
            w = self.tabs.widget(r)
            w.connect_all()

    def disconnect_all(self):
        self.addChar.clicked.disconnect()
        self.removeChar.clicked.disconnect()

        self.listWidget.currentItemChanged.disconnect()
        self.listWidget.itemChanged.disconnect()

        for r in range(self.tabs.count()):
            w = self.tabs.widget(r)
            w.disconnect_all()

    def disable_stuff(self, disabled):

        self.addChar.setDisabled(disabled)
        self.removeChar.setDisabled(disabled)

    def init_UI(self):

        ##  Just to make life easier
        get_icon = Icons().get_icon

        ##  List of characters
        self.listWidget = QListWidget(self)

        ##  Add character button
        self.addChar = QPushButton(QIcon(get_icon("list-add")), "")
        self.addChar.setToolTip("Add a character")

        ##  Remove character button
        self.removeChar = QPushButton(QIcon(get_icon("list-remove")), "")
        self.removeChar.setToolTip("Remove selected character")

        ##  Bullshit to make qsplitter work
        self.list = MyListWidget(self)

        ##  Initial template
        self.template = self.parent.get_template()

        ##  Tab widget
        self.tabs = QTabWidget()

        self.load_tabs()

        ##  Tabs start out disabled
        self.tabs.setDisabled(True)

        ##  Connect it up
        self.connect_all()

        ##============= LAYOUTS

        splitter = QSplitter()
        splitter.addWidget(self.list)
        splitter.addWidget(self.tabs)

        splitter.setSizes([(WINDOW_WIDTH * .25), (WINDOW_WIDTH * .75)])

        ##  Set the layout
        hbox = QHBoxLayout()
        hbox.addWidget(splitter)
        self.setLayout(hbox)

    def load_tabs(self):
        if self.template != None:
            tabIndex = 0
            for tab in self.template.iter("tab"):
                widget = Tab(self, tabIndex, tab)
                tabIndex += 1
                self.tabs.addTab(widget, tab.find("title").text)

    def add_character(self):

        char = CharacterInfo(self.template)
        self.characters.append(char)

        li = QListWidgetItem(char.listName)
        li.setFlags(li.flags() | Qt.ItemIsEditable)
        self.listWidget.addItem(li)
        self.listWidget.setCurrentItem(li)

        ##  Enable the tabs widget
        self.tabs.setDisabled(False)

    def remove_character(self):

        idx = self.listWidget.currentRow()
        li = self.listWidget.item(idx)
        if li != None:
            ##  Kill whatever character at the index
            null = self.characters.pop(idx)

            ni = self.listWidget.item(idx + 1)
            pi = self.listWidget.item(idx - 1)

            #self.listWidget.currentItemChanged.disconnect()

            self.disconnect_all()

            sip.delete(li)

            self.listWidget.currentItemChanged.connect(self.item_changed)
            if ni != None:
                self.listWidget.setCurrentItem(ni)
                idx = self.listWidget.currentRow()
                self.charIndex = idx
                self.load_values(self.characters[idx])
            elif pi != None:
                self.listWidget.setCurrentItem(pi)
                idx = self.listWidget.currentRow()
                self.charIndex = idx
                self.load_values(self.characters[idx])
            else:
                self.charIndex = -1
                self.tabs.setDisabled(True)
                self.listWidget.currentItemChanged.connect(self.item_changed)
                self.clear_values()

            self.connect_all()

    def item_changed(self):

        li = self.listWidget.currentItem()
        if li != None:
            self.charIndex = self.listWidget.currentRow()
            self.load_values(self.characters[self.charIndex])

    def item_text_changed(self):

        li = self.listWidget.currentItem()
        if li != None:
            self.characters[self.charIndex].listName = li.text()

    def load_values(self, char):

        for t in range(len(self.characters[self.charIndex].tabs)):
            tab = self.tabs.widget(t)
            tab.load_values(char)

    def clear_values(self):
        for t in range(self.tabs.count()):
            w = self.tabs.widget(t)
            w.clear_values()
        #if len( self.characters ) > 0:
        #    for t in range( len(self.characters[ self.charIndex ].tabs )):
        #        tab = self.tabs.widget( t )
        #        tab.clear_values()

    def clear_all(self):

        ##  Kill characters and disable the tabs
        self.characters = []
        self.tabs.setDisabled(True)

        ##  Kill tabs
        self.tabs.clear()

        ##  Kill the list
        self.listWidget.clear()

    def load_list(self):

        for char in self.characters:

            li = QListWidgetItem(char.listName)
            li.setFlags(li.flags() | Qt.ItemIsEditable)
            self.listWidget.addItem(li)

    def reload(self, template, characters):
        self.disconnect_all()

        self.clear_all()
        self.template = template

        #c = characters[ 0 ]
        #print( c.tabs[ 0 ][0][ "name" ] )

        self.characters = characters
        self.load_list()
        self.load_tabs()

        self.connect_all()

        li = self.listWidget.item(0)
        if li != None:
            self.listWidget.setCurrentItem(li)
            self.tabs.setDisabled(False)