Пример #1
1
class SourceViewer(QDialog):
    def __init__(self, browser):
        super(SourceViewer, self).__init__(browser.parentWidget())

        layout = QVBoxLayout()
        layout.setContentsMargins(4, 4, 4, 4)
        self.setLayout(layout)
        
        self.urlLabel = QLabel(wordWrap=True)
        layout.addWidget(self.urlLabel)
        self.textbrowser = QTextBrowser()
        layout.addWidget(self.textbrowser)
        
        self.urlLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.textbrowser.setLineWrapMode(QTextBrowser.NoWrap)
        
        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        app.translateUI(self)
        qutil.saveDialogSize(self, "helpbrowser/sourceviewer/size", QSize(400, 300))
        
    def translateUI(self):
        self.setWindowTitle(app.caption(_("LilyPond Source")))
        
    def readSettings(self):
        data = textformats.formatData('editor')
        self.textbrowser.setPalette(data.palette())
        self.textbrowser.setFont(data.font)
        highlighter.highlight(self.textbrowser.document())
        
    def showReply(self, reply):
        reply.setParent(self)
        self.urlLabel.setText(reply.url().toString())
        self._reply = reply
        reply.finished.connect(self.loadingFinished)
        self.textbrowser.clear()
        self.show()
        
    def loadingFinished(self):
        data = self._reply.readAll()
        self._reply.close()
        self._reply.deleteLater()
        del self._reply
        self.textbrowser.clear()
        self.textbrowser.setText(str(data, 'utf-8', 'replace'))
        highlighter.highlight(self.textbrowser.document())
Пример #2
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)
        # 키보드에 엔터를 눌렀는지 확인해주는 이벤트
        # 엔터를 누르면 append_text를 받아와서 입력값 자동 저장

        self.tb = QTextBrowser()  #QTextBrowser() 클래스를 이용해서 텍스트 브라우저 객체 생성
        self.tb.setAcceptRichText(True)  # 서식 있는 텍스트(Rich text)를 사용할 수 있음
        # 디폴트로 True이기 때문에 없어도 되는 부분!
        self.tb.setOpenExternalLinks(True)  # 외부 링크로의 연결 가능

        self.clear_btn = QPushButton('Clear')  # 버튼을 클릭하면
        self.clear_btn.pressed.connect(self.clear_text)  # Clear_text 메소드 호출

        vbox = QVBoxLayout()  # 레이아웃 해주기 위한 vbox 객체 생성!
        vbox.addWidget(self.le, 0)  # .addWidget() 순서 정해줄 수 있음!
        vbox.addWidget(self.tb, 1)
        vbox.addWidget(self.clear_btn, 2)
        self.setLayout(vbox)
        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 300)
        self.show()

    def append_text(self):
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()  # 입력값 초기화 시켜주는 함수!

    def clear_text(self):
        self.tb.clear()
Пример #3
0
class CheckInputWidget(QWidget, MooseWidget):
    """
    Runs the executable with "--check-input" on the input file and stores the results.
    Signals:
        needInputFile: Emitted when we need the input file. Argument is the path where the input file will be written.
    """
    needInputFile = pyqtSignal(str)

    def __init__(self, **kwds):
        super(CheckInputWidget, self).__init__(**kwds)

        self.input_file = "peacock_check_input.i"
        self.top_layout = WidgetUtils.addLayout(vertical=True)
        self.setLayout(self.top_layout)
        self.output = QTextBrowser(self)
        self.output.setStyleSheet(
            "QTextBrowser { background: black; color: white; }")
        self.output.setReadOnly(True)
        self.top_layout.addWidget(self.output)
        self.button_layout = WidgetUtils.addLayout()
        self.top_layout.addLayout(self.button_layout)
        self.hide_button = WidgetUtils.addButton(self.button_layout, self,
                                                 "Hide", lambda: self.hide())
        self.check_button = WidgetUtils.addButton(self.button_layout, self,
                                                  "Check", self._check)
        self.resize(800, 500)
        self.setup()
        self.path = None

    def cleanup(self):
        try:
            os.remove(self.input_file)
        except:
            pass

    def check(self, path):
        """
        Runs the executable with "--check-input" and adds the output to the window
        Input:
            path[str]: Path to the executable
        """
        self.path = path
        self._check()

    def _check(self):
        """
        Runs the executable with "--check-input" and adds the output to the window
        """
        input_file = os.path.abspath(self.input_file)
        self.needInputFile.emit(input_file)
        self.output.clear()
        try:
            args = ["-i", input_file, "--check-input"]
            output = ExeLauncher.runExe(self.path, args, print_errors=False)
            output_html = TerminalUtils.terminalOutputToHtml(output)
            self.output.setHtml("<pre>%s</pre>" % output_html)
        except Exception as e:
            output_html = TerminalUtils.terminalOutputToHtml(str(e))
            self.output.setHtml("<pre>%s</pre>" % output_html)
        self.cleanup()
Пример #4
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        self.clear_btn = QPushButton('Clear')
        self.clear_btn.pressed.connect(self.clear_text)

        vbox = QVBoxLayout()
        vbox.addWidget(self.le, 0)
        vbox.addWidget(self.tb, 1)
        vbox.addWidget(self.clear_btn, 2)

        self.setLayout(vbox)

        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 300)
        self.show()

    def append_text(self):
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()

    def clear_text(self):
        self.tb.clear()
Пример #5
0
def showPointsCharacteristics(characteristics: dict,
                              textBrowser: QTextBrowser):
    textBrowser.clear()
    textBrowser.append(
        "АНАЛІЗ ДВОВИМІРНОГО ОБ'ЄКТУ\n \t\t\t|---Точкові статистичні оцінки---|\n"
    )
    textBrowser.append(getPointCharacteristicsTable(characteristics))
Пример #6
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        self.le = QLineEdit()
        self.le.setPlaceholderText('기본 값 유윈스 학사공')
        self.le.returnPressed.connect(self.get_url_subject)

        self.btn = QPushButton('Start')
        self.btn.clicked.connect(self.get_url_subject)

        self.lbl = QLabel('과를 입력하세요.')

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        grid = QGridLayout()
        grid.addWidget(self.le, 0, 0, 1, 3)
        grid.addWidget(self.btn, 0, 3, 1, 1)
        grid.addWidget(self.lbl, 1, 0, 1, 4)
        grid.addWidget(self.tb, 2, 0, 1, 4)

        self.setLayout(grid)

        self.setWindowTitle('Web Crawler')
        self.setGeometry(100, 100, 450, 650)
        self.show()

    def get_url_subject(self):
        urls = []
        subjects = []

        major = self.le.text()
        if not major:
            self.lbl.setText('학사 공지사항입니다.')
            self.tb.clear()
            req = requests.get(
                'https://uwins.ulsan.ac.kr/JBGJ/B/MIB01S.aspx?MenuID=MIB01S!1')
            html = req.text
            soup = BeautifulSoup(html, 'html.parser')
            id_links = soup.select('td:nth-child(1)')
            subject_links = soup.select('td.textWrap.Left')
            for id_link in id_links:
                id = id_link.text.strip()
                url = 'https://uwins.ulsan.ac.kr/JBGJ/B/MIB02S.aspx?MenuID=MIB01S!1&board_gb=A38002&seq=' + id + '&Grade=3&current_page=1'
                urls.append(url)

            for subject_link in subject_links:
                subject = subject_link.text.strip()
                subjects.append(subject)
            for i in range(10):
                self.tb.append(
                    str(i + 1) + '. ' + subjects[i] + ' (' + '<a href="' +
                    urls[i] + '">링크</a>' + ')')
Пример #7
0
class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.setWindowTitle('IndeedCrawler')

        self.url_line = QLineEdit(self)  # Get start url
        self.ua_line = QLineEdit(self)  # Input USER_AGENT
        self.obey_combo = QComboBox(self)  # Decide ROBOTSTXT_OBEY
        self.job_num = QLineEdit(self)
        self.obey_combo.addItems(['Yes', 'No'])
        self.log_browser = QTextBrowser(self)  # Log output
        self.crawl_btn = QPushButton('Start Crawling', self)  # Start Crawling
        self.crawl_btn.clicked.connect(self.crawl_slot)

        # Layout
        self.h_layout = QHBoxLayout()
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(QLabel('Input start url'))
        self.v_layout.addWidget(self.url_line)
        self.h_layout.addWidget(
            QLabel('Iinput total job numbers to be crawled'))
        self.h_layout.addWidget(self.job_num)
        self.h_layout.addWidget(QLabel('Input User-Agent'))
        self.h_layout.addWidget(self.ua_line)
        self.h_layout.addWidget(QLabel('Obey Robot.txt'))
        self.h_layout.addWidget(self.obey_combo)
        self.v_layout.addLayout(self.h_layout)
        self.v_layout.addWidget(QLabel('Output'))
        self.v_layout.addWidget(self.log_browser)
        self.v_layout.addWidget(self.crawl_btn)
        self.setLayout(self.v_layout)

        self.Q = Manager().Queue()
        self.log_thread = LogThread(self)

    def crawl_slot(self):
        if self.crawl_btn.text() == 'Start Crawling':
            self.log_browser.clear()
            self.crawl_btn.setText('Stop Crawling')
            start_url = self.url_line.text()
            ua = self.ua_line.text().strip()
            try:
                job_num = int(self.job_num.text())
            except:
                print('Jobs number must be a integer')
            is_obey = True if self.obey_combo.currentText() == 'Yes' else False
            self.p = Process(target=crawl,
                             args=(self.Q, ua, is_obey, start_url, job_num))
            self.p.start()
            self.log_thread.start()
        else:
            self.crawl_btn.setText('Start Crawling')
            self.p.terminate()
            self.log_thread.terminate()

    def closeEvent(self, event):
        self.p.terminate()
        self.log_thread.terminate()
Пример #8
0
class SummaryWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent
        self.setWindowTitle(self.tr("Installation Information"))
        self.setLayout(QVBoxLayout())

        label1 = QLabel()
        label1.setText(self.tr("<h3>Take a look at the summary of your choices for the installation.</h3>"))
        self.layout().addWidget(label1)

        label2 = QLabel()
        label2.setText(self.tr("<h1>System Location</h1>"))
        self.layout().addWidget(label2)

        self.textbrowser1 = QTextBrowser()
        self.layout().addWidget(self.textbrowser1)

        label3 = QLabel()
        label3.setText(self.tr("<h1>Keyboard Layout</h1>"))
        self.layout().addWidget(label3)

        self.textbrowser2 = QTextBrowser()
        self.layout().addWidget(self.textbrowser2)

        label4 = QLabel()
        label4.setText(self.tr("<h1>Disk Partition</h1>"))
        self.layout().addWidget(label4)

        self.textbrowser3 = QTextBrowser()
        self.layout().addWidget(self.textbrowser3)

    def showEvent(self, event):
        self.textbrowser1.setText(self.tr("System time will be set to {}.\nSystem language will be set to {}.")
                                  .format(self.parent.lilii_settings["timezone"], self.parent.lilii_settings["lang"]))

        variant = None
        if self.parent.lilii_settings["keyboard_variant"] != None:
            variant = self.parent.lilii_settings["keyboard_variant"][-1]
        else:
            variant = "Default"

        self.textbrowser2.setText(self.tr("Keyboard model is choosen as {}.\nKeyboard kind is choosen as {}/{}.")
                                  .format(self.parent.lilii_settings["keyboard_model"][-1],
                                          self.parent.lilii_settings["keyboard_layout"][-1], variant))

        self.textbrowser3.clear()
        if self.parent.lilii_settings["/"]:
            self.textbrowser3.append(self.tr("Root directory is {}.").format(self.parent.lilii_settings["/"]))

        if self.parent.lilii_settings["/home"]:
            self.textbrowser3.append(self.tr("Home directory is {}.").format(self.parent.lilii_settings["/home"]))

        if is_efi() and self.parent.lilii_settings["/boot/efi"]:
            self.textbrowser3.append(self.tr("Bootloader installation directory is {}.").format(self.parent.lilii_settings["/boot/efi"]))

        else:
            self.textbrowser3.append(self.tr("Bootloader installation disk: {}").format(self.parent.lilii_settings["bootloader"]))
Пример #9
0
def showProtocol(characteristics: dict, textBrowser: QTextBrowser):
    textBrowser.clear()
    textBrowser.append(
        "АНАЛІЗ ОДНОВИМІРНОГО ОБ'ЄКТУ\n \t\t\t\t\t|---Точкові статистичні оцінки---|\n"
    )
    textBrowser.append(getPointCharacteristicsTable(characteristics['point']))
    textBrowser.append("\t\t\t\t\t|---Інтервальні статистичні оцінки---|\n")
    textBrowser.append(
        getIntervalCharacteristicsTable(characteristics['interval']))
Пример #10
0
class CheckInputWidget(QWidget, MooseWidget):
    """
    Runs the executable with "--check-input" on the input file and stores the results.
    Signals:
        needInputFile: Emitted when we need the input file. Argument is the path where the input file will be written.
    """
    needInputFile = pyqtSignal(str)

    def __init__(self, **kwds):
        super(CheckInputWidget, self).__init__(**kwds)

        self.input_file = "peacock_check_input.i"
        self.top_layout = WidgetUtils.addLayout(vertical=True)
        self.setLayout(self.top_layout)
        self.output = QTextBrowser(self)
        self.output.setStyleSheet("QTextBrowser { background: black; color: white; }")
        self.output.setReadOnly(True)
        self.top_layout.addWidget(self.output)
        self.button_layout = WidgetUtils.addLayout()
        self.top_layout.addLayout(self.button_layout)
        self.hide_button = WidgetUtils.addButton(self.button_layout, self, "Hide", lambda: self.hide())
        self.check_button = WidgetUtils.addButton(self.button_layout, self, "Check", self._check)
        self.resize(800, 500)
        self.setup()
        self.path = None

    def cleanup(self):
        try:
            os.remove(self.input_file)
        except:
            pass

    def check(self, path):
        """
        Runs the executable with "--check-input" and adds the output to the window
        Input:
            path[str]: Path to the executable
        """
        self.path = path
        self._check()

    def _check(self):
        """
        Runs the executable with "--check-input" and adds the output to the window
        """
        input_file = os.path.abspath(self.input_file)
        self.needInputFile.emit(input_file)
        self.output.clear()
        try:
            args = ["-i", input_file, "--check-input"]
            output = ExeLauncher.runExe(self.path, args, print_errors=False)
            output_html = TerminalUtils.terminalOutputToHtml(output)
            self.output.setHtml("<pre>%s</pre>" % output_html)
        except Exception as e:
            output_html = TerminalUtils.terminalOutputToHtml(str(e))
            self.output.setHtml("<pre>%s</pre>" % output_html)
        self.cleanup()
class MyApp(QWidget):

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

        self.initUI()

    def initUI(self):

        self.le = QLineEdit()
        self.le.setPlaceholderText('기본 값 유윈스 학사공')
        self.le.returnPressed.connect(self.ulsan_urls_subjects)

        self.btn = QPushButton('Start')
        self.btn.clicked.connect(self.ulsan_urls_subjects)

        self.lbl = QLabel('과를 입력하세요.')

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        grid = QGridLayout()
        grid.addWidget(self.le, 0, 0, 1, 3)
        grid.addWidget(self.btn, 0, 3, 1, 1)
        grid.addWidget(self.lbl, 1, 0, 1, 4)
        grid.addWidget(self.tb, 2, 0, 1, 4)

        self.setLayout(grid)

        self.setWindowTitle('Web Crawler')
        self.setGeometry(100, 100, 450, 650)
        self.show()
    def ulsan_urls_subjects(self):
        ulsan_urls = []
        ulsan_subjects = []
        ulsan_
        major = self.le.text()
        if not major:
            self.lbl.setText('울산대 홈페이지 공지사항입니다.')
            self.tb.clear()
            req = requests.get('http://www.ulsan.ac.kr/unews/news/notice.aspx?o=L')
            html = req.text
            soup = BeautifulSoup(html, 'html.parser')
            id_links = soup.select('tr > td.no')
            subject_links = soup.select('tr > td.title')
            for id_link in id_links:
                id = id_link.text.strip()
                url = 'http://www.ulsan.ac.kr/unews/news/notice.aspx?o=R&a_no='+str(int(id)+2468)
                urls.append(url)
            for subject_link in subject_links:
                subject = subject_link.text.strip()
                subjects.append(subject)
            for i in range(10):
                self.tb.append(str(i + 1) + '. ' + subjects[i] + ' (' + '<a href="' + urls[i] + '">링크</a>' + ')')
Пример #12
0
class PushButton(QWidget):
    def __init__(self, func):
        self.func = func
        self.res = None
        super(PushButton,self).__init__()
        self.initUI()
    def initUI(self):

        self.syncButton = QPushButton('Sync EMEA Pacfile')
        self.logButton = QPushButton('Show Status')
        self.clearButton = QPushButton('Clear Status')
        self.closeButton = QPushButton('Close Window')

        self.lcd = QTextBrowser()
        self.lcd.setFixedHeight(90)
        self.lcd.setFont(QFont("Microsoft YaHei", 10))

        self.syncButton.clicked.connect(self.sync)
        self.closeButton.clicked.connect(self.close)
        self.clearButton.clicked.connect(self.clearText)
        self.logButton.clicked.connect(self.showLog)

        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(self.syncButton)
        buttonLayout.addWidget(self.logButton)
        buttonLayout.addWidget(self.clearButton)
        buttonLayout.addWidget(self.closeButton)


        mainLayout = QVBoxLayout()
        mainLayout.addLayout(buttonLayout)
        mainLayout.addWidget(self.lcd)


        self.setLayout(mainLayout)
        self.setWindowTitle("PushButton_test")
        self.show()

    def sync(self):
        self.res = 'process'
        self.res = self.func()
        logger.warning('End: Sync process finish')

    def clearText(self):
        self.lcd.clear()

    def showLog(self):
        res_mesg = {
            'fail': 'Fail to sync, please check log file',
            'success': 'Sync finish, please verify',
            'process': 'Sync is in process, please wait',
            None: 'Sync has not start, please click "Sync EMEA Pacfile"'
        }
        self.lcd.setText(res_mesg[self.res])
Пример #13
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        self.clear_btn = QPushButton('Clear')
        self.clear_btn.pressed.connect(self.clear_text)

        self.lbl1 = QLabel('Enter your sentence:')
        self.te = QTextEdit()
        self.te.setAcceptRichText(False)
        self.lbl2 = QLabel('The number of words is 0')

        self.te.textChanged.connect(self.text_changed)

        layout = QHBoxLayout()
        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.lbl1)
        vbox1.addWidget(self.te)
        vbox1.addWidget(self.lbl2)
        vbox1.addStretch()

        vbox = QVBoxLayout()
        vbox.addWidget(self.le, 0)
        vbox.addWidget(self.tb, 1)
        vbox.addWidget(self.clear_btn, 2)
        layout.addLayout(vbox)
        layout.addLayout(vbox1)

        self.setLayout(layout)

        self.setWindowTitle('으에에ㅔ')
        self.setGeometry(300, 300, 700, 800)
        self.show()

    def append_text(self):
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()

    def clear_text(self):
        self.tb.clear()

    def text_changed(self):
        text = self.te.toPlainText()
        self.lbl2.setText('The number of words is ' + str(len(text.split())))
Пример #14
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        self.le = QLineEdit()
        self.le.setPlaceholderText('yymmdd')
        self.le.returnPressed.connect(self.crawl_news)

        self.btn = QPushButton('Start')
        self.btn.clicked.connect(self.crawl_news)

        self.lbl = QLabel('날짜를 입력하세요.')

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        grid = QGridLayout()
        grid.addWidget(self.le, 0, 0, 1, 3)
        grid.addWidget(self.btn, 0, 3, 1, 1)
        grid.addWidget(self.lbl, 1, 0, 1, 4)
        grid.addWidget(self.tb, 2, 0, 1, 4)

        self.setLayout(grid)

        self.setWindowTitle('Web Crawler')
        self.setGeometry(100, 100, 450, 650)
        self.show()

    def crawl_news(self):
        date = self.le.text()

        if date:
            self.lbl.setText('[20' + str(date) + '] 많이 본 뉴스입니다.')
            self.tb.clear()
            url_news = 'https://news.naver.com'
            url = url_news + '/main/ranking/popularDay.nhn?rankingType=popular_day&date=20' + date
            r = requests.get(url)
            html = r.content
            soup = BeautifulSoup(html, 'html.parser')
            titles_html = soup.select(
                '.ranking_section > ol > li > dl > dt > a')

            for i in range(len(titles_html)):
                title = titles_html[i].text
                link = url_news + titles_html[i].get('href')
                self.tb.append(
                    str(i + 1) + '. ' + title + ' (' + '<a href="' + link +
                    '">링크</a>' + ')')
Пример #15
0
class ImportTab(QWidget):
    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)
        self.left = 10
        self.top = 10
        self.width = STANDARD_W
        self.height = STANDARD_H
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setUI()

    def setUI(self):
        self.setWindowTitle('Import Data')
        self.vbox_layout = QVBoxLayout()

        self.firstrade_CSV_import_btn = QPushButton(
            "Import Firstrade standard account CSV file")
        self.text_browser = QTextBrowser()

        self.vbox_layout.addWidget(self.firstrade_CSV_import_btn)
        self.vbox_layout.addWidget(self.text_browser)

        self.setLayout(self.vbox_layout)  # finally

        self.firstrade_CSV_import_btn.clicked.connect(
            partial(
                self._import_data,
                title="Import Firstrade standard account history CSV file"))

    def _import_data(self, title):
        self.text_browser.clear()
        filepath = self._file_selector(title)
        self.text_browser.append(
            "Ready to import data, source from '{}'".format(filepath))
        try:
            success_count = FTDB.importFTStandardCSV(filepath,
                                                     self.text_browser)
            self.text_browser.append(
                "Successful importing: {}".format(success_count))
            self.text_browser.append("Import done.".format())
        except (TypeError, FileNotFoundError) as err:
            self.text_browser.append(
                "Invalid filepath (given: '{}'), please select again. (error msg: {})"
                .format(filepath, err))
        except Exception as err:
            self.text_browser.append("Import Error: {}".format(err))
            self.text_browser.append("{}".format(traceback.format_exc()))

    def _file_selector(self, title):
        fp = FileHandler(title)
        filepath = fp.openFileNameDialog()
        fp.show()
        fp.deleteLater()
        return filepath
Пример #16
0
class CrawlWindows(QWidget):
    def __init__(self):
        super(CrawlWindows, self).__init__()
        self.resize(600, 300)
        self.setWindowIcon(QIcon(':icons/favicon.ico'))
        self.setWindowTitle('Books to scrape (http://books.toscrape.com)')

        self.ua_line = QLineEdit(self)
        self.obey_combo = QComboBox(self)
        self.obey_combo.addItems(['Yes', 'No'])
        # self.save_location = QLineEdit(self)
        self.log_browser = QTextBrowser(self)
        self.crawl_button = QPushButton('Start crawl', self)
        self.crawl_button.clicked.connect(
            lambda: self.crawl_slot(self.crawl_button))

        self.h_layout = QHBoxLayout()
        self.v_layout = QVBoxLayout()
        self.h_layout.addWidget(QLabel('Input User-Agent:'))
        self.h_layout.addWidget(self.ua_line)
        # self.h_layout.addWidget(QLabel('Save path'))
        # self.h_layout.addWidget(self.save_location)
        self.h_layout.addWidget(QLabel('Robot protocol:'))
        self.h_layout.addWidget(self.obey_combo)
        self.v_layout.addLayout(self.h_layout)
        self.v_layout.addWidget(QLabel('Output log box:'))
        self.v_layout.addWidget(self.log_browser)
        self.v_layout.addWidget(self.crawl_button)
        self.setLayout(self.v_layout)

        self.p = None
        self.Q = Manager().Queue()
        self.log_thread = LogThread(self)

    def crawl_slot(self, button):
        if button.text() == 'Start crawl':
            self.log_browser.clear()
            self.crawl_button.setText('Stop crawl')
            ua = self.ua_line.text().strip()
            is_obey = True if self.obey_combo.currentText() == 'Yes' else False
            # save_location = self.save_location.text().strip()
            self.p = Process(target=crawl_run, args=(self.Q, ua, is_obey))
            self.log_browser.setText('The collection process is starting...')
            self.p.start()

            self.log_thread.start()
        else:
            self.crawl_button.setText('Start crawl')
            self.p.terminate()

            self.log_thread.terminate()
Пример #17
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)
        # 줄편집기 하나를 만들었습니다.
        #
        # Enter키를 누르면 append_text 메서드가 호출됩니다.

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)
        # QTextBrowser() 클래스를 이용해서 텍스트 브라우저를 하나 만들었습니다.
        #
        # setAcceptRichText()를 True로 설정해주면, 서식 있는 텍스트
        # (Rich text)를 사용할 수 있습니다.
        #
        # 디폴트로 True이기 때문에 없어도 되는 부분입니다.
        #
        # setOpenExternalLinks()를 True로 설정해주면, 외부 링크로의 연결이 가능합니다.

        self.clear_btn = QPushButton('Clear')
        self.clear_btn.pressed.connect(self.clear_text)
        # clear_btn을 클릭하면, clear_text 메서드가 호출됩니다.

        vbox = QVBoxLayout()
        vbox.addWidget(self.le, 0)
        vbox.addWidget(self.tb, 1)
        vbox.addWidget(self.clear_btn, 2)

        self.setLayout(vbox)

        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 300)
        self.show()

    def append_text(self):
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()
        # append_text 메서드는 줄편집기에 작성된 텍스트
        # (self.le.text())를 텍스트 브라우저 (self.tb)에 append 해주는 기능을 합니다.
        #
        # 텍스트가 텍스트 브라우저에 추가되면, clear 메서드를 이용해서 줄편집기에 있던
        # 텍스트는 없애줍니다.

    def clear_text(self):
        self.tb.clear()
Пример #18
0
class DebugInfo(QDockWidget):
    def __init__(self, parent=None):
        super(DebugInfo, self).__init__()
        self.head_info = None

        self.setWindowTitle('日志')
        self.setFeatures(QDockWidget.NoDockWidgetFeatures
                         | QDockWidget.DockWidgetMovable
                         | QDockWidget.DockWidgetFloatable)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.dock_widget_contents = QWidget()
        self.setWidget(self.dock_widget_contents)

        self.info_text_browser = QTextBrowser(self.dock_widget_contents)
        self.info_text_browser.setReadOnly(True)

        self.horizontal_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                             QSizePolicy.Minimum)
        self.clear_button = QPushButton("清除记录", self.dock_widget_contents)

        self.hLayout = QHBoxLayout()
        self.hLayout.addItem(self.horizontal_spacer)
        self.hLayout.addWidget(self.clear_button)

        self.vLayout = QVBoxLayout(self.dock_widget_contents)
        self.vLayout.setSpacing(4)
        self.vLayout.setContentsMargins(4, 4, 4, 4)
        self.vLayout.addWidget(self.info_text_browser)
        self.vLayout.addLayout(self.hLayout)

        self.clear_button.clicked.connect(self.clear)

        # self.dock_widget_contents.setMinimumWidth(300)

    def set_head_info(self, head_info):
        self.head_info = head_info
        self.clear()

    def set_text_browser(self, text_info):
        pass

    def clear(self):
        self.info_text_browser.clear()
        if self.head_info is not None:
            self.info_text_browser.append(self.head_info)
            h = self.height()
            w = self.width()
            self.resize(w, 10)
            self.resize(w, h)
Пример #19
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.icon = dir_icon + 'icon_qt.png'
        self.title = 'Ex5.19_QTextBrowser'
        self.posXY = (600, 45)
        self.windowSize = (300, 300)
        self.initUI()
        self.showBasic()

    def initUI(self):
        lb1 = QLabel('TEXT HISTORY :')
        lb2 = QLabel('TYPE & ENTER to Store ABOVE!')

        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        clear_btn = QPushButton('Clear')
        clear_btn.pressed.connect(self.clear_text)

        vbox = QVBoxLayout()
        vbox.addWidget(lb1)
        vbox.addWidget(self.tb, 1)
        vbox.addWidget(lb2)
        vbox.addWidget(self.le, 0)
        vbox.addWidget(clear_btn, 2)

        self.setLayout(vbox)

    def showBasic(self):
        """Basci Attribution & Geometry display"""
        self.setWindowIcon(QIcon(self.icon))
        self.setWindowTitle(self.title)
        self.setGeometry(*self.posXY, *self.windowSize)
        self.show()

    def append_text(self):
        """CallBack() When le.returnPressed.connect"""
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()

    def clear_text(self):
        """CallBack() When clear_btn.pressed.connect"""
        self.tb.clear()
Пример #20
0
class SourceViewer(QDialog):
    def __init__(self, browser):
        super(SourceViewer, self).__init__(browser.parentWidget())

        layout = QVBoxLayout()
        layout.setContentsMargins(4, 4, 4, 4)
        self.setLayout(layout)

        self.urlLabel = QLabel(wordWrap=True)
        layout.addWidget(self.urlLabel)
        self.textbrowser = QTextBrowser()
        layout.addWidget(self.textbrowser)

        self.urlLabel.setSizePolicy(QSizePolicy.Preferred,
                                    QSizePolicy.Preferred)
        self.textbrowser.setLineWrapMode(QTextBrowser.NoWrap)

        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        app.translateUI(self)
        qutil.saveDialogSize(self, "helpbrowser/sourceviewer/size",
                             QSize(400, 300))

    def translateUI(self):
        self.setWindowTitle(app.caption(_("LilyPond Source")))

    def readSettings(self):
        data = textformats.formatData('editor')
        self.textbrowser.setPalette(data.palette())
        self.textbrowser.setFont(data.font)
        highlighter.highlight(self.textbrowser.document())

    def showReply(self, reply):
        reply.setParent(self)
        self.urlLabel.setText(reply.url().toString())
        self._reply = reply
        reply.finished.connect(self.loadingFinished)
        self.textbrowser.clear()
        self.show()

    def loadingFinished(self):
        data = self._reply.readAll()
        self._reply.close()
        self._reply.deleteLater()
        del self._reply
        self.textbrowser.clear()
        self.textbrowser.setText(str(data, 'utf-8', 'replace'))
        highlighter.highlight(self.textbrowser.document())
Пример #21
0
class LogWidget(QWidget, MooseWidget):
    """
    A widget that shows the log.

    This ties into mooseutils.message.mooseMessage which will
    emit a signal on mooseutils.message.messageEmitter
    This widget listens to messageEmitter and puts
    the text in the widget.
    Color text is supported.
    """
    def __init__(self, **kwds):
        """
        Constructor.
        """
        super(LogWidget, self).__init__(**kwds)
        self.top_layout = WidgetUtils.addLayout(vertical=True)
        self.setLayout(self.top_layout)
        self.log = QTextBrowser(self)
        self.log.setStyleSheet(
            "QTextBrowser { background: black; color: white; }")
        self.log.setReadOnly(True)
        message.messageEmitter.message.connect(self._write)
        self.button_layout = WidgetUtils.addLayout()
        self.hide_button = WidgetUtils.addButton(self.button_layout, self,
                                                 "Hide", lambda: self.hide())
        self.clear_button = WidgetUtils.addButton(self.button_layout, self,
                                                  "Clear",
                                                  lambda: self.log.clear())
        self.top_layout.addWidget(self.log)
        self.top_layout.addLayout(self.button_layout)
        self.resize(800, 500)

    @pyqtSlot(str, str)
    def _write(self, msg, color):
        """
        This is the slot that will write the message to the widget.

        Inputs:
            msg: The message to write
            color: The color to write the text in.
        """
        if not msg:
            return

        msg = msg.encode(
            'utf-8'
        )  # make sure if there are bad characters in the message that we can show them.

        if not color or color == "None":
            color = "white"
        else:
            color = str(color)

        if msg.find("\n") >= 0:
            self.log.insertHtml(
                '<div style="color:%s"><pre><code>%s</code></pre></div><br>' %
                (color.lower(), escape(msg)))
        else:
            self.log.insertHtml('<div style="color:%s">%s</div><br>' %
                                (color.lower(), escape(msg)))
Пример #22
0
class ConsoleWidget(QDialog):
    _close_single = pyqtSignal()
    _send_command = pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super(ConsoleWidget, self).__init__(*args, **kwargs)

        self.width_height = 300, 700
        self.resize(*self.width_height)
        self.setFixedSize(*self.width_height)
        self.setWindowTitle('Super Continent Console')

        self.text_browser = QTextBrowser(parent=self)
        self.line_edit = QLineEdit(parent=self)
        self.line_edit.returnPressed.connect(self.command)

        self.init()
        self.connect_slot()
        self.show()

    def closeEvent(self, a0: QCloseEvent) -> None:
        self._close_single.emit()

    def init(self):
        layout = QVBoxLayout(self)
        layout.addWidget(self.text_browser)
        layout.addWidget(self.line_edit)
        self.setLayout(layout)

    def connect_slot(self):
        parent = self.parent()
        self._close_single.connect(parent.close_console_dialog)
        self._send_command.connect(parent.print_command)

    def command(self):
        cmd = self.line_edit.text()
        self.line_edit.clear()
        match cmd:
            case 'clear':
                self.text_browser.clear()
            case 'close':
                self.close()
            case _:
                self.text_browser.append(cmd)
                self._send_command.emit(cmd)
class MyTextBrowser(QGroupBox):
    def __init__(self):
        super().__init__()
        self.setTitle('QTextBrowser')
        self.init_ui()

    def init_ui(self):
        self.le = QLineEdit()
        self.le.returnPressed.connect(self.append_text)

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)

        self.clear_btn = QPushButton('Clear')
        self.clear_btn.pressed.connect(self.clear_text)

        self.init_text()

        layout = QVBoxLayout()
        layout.addWidget(self.le)
        layout.addWidget(self.tb)
        layout.addWidget(self.clear_btn)

        self.setLayout(layout)

    def init_text(self):
        texts = [
            '<i>Italic</i>', '<p style="color: red">Red</p>',
            '<p style="font-size: 20px">20px</p>',
            '<a href="https://www.naver.com">Naver</a>'
        ]
        for t in texts:
            self.tb.append(t)

    def append_text(self):
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()

    def clear_text(self):
        self.tb.clear()
Пример #24
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()  # QLineEdit() : HTML 태그형태로 입력할 수 있는 한 줄 짜리 입력창
        self.le.returnPressed.connect(
            self.append_text
        )  # 키보드에 엔터가 눌렸는지 안눌렸는지 알아내는 returnPressed.엔터를 누르면 값을 append_text로 전달

        self.tb = QTextBrowser()  # 태그를 해석해서 출력시켜줄 텍스트브라우저 객체 생성
        self.tb.setAcceptRichText(
            True
        )  # 텍스트 브라우저에 출력된 글씨들을 복사한다던지, 이와 같이 해당 글자를 접근 가능하게 할거면 True, 막을거면 False
        self.tb.setOpenExternalLinks(
            True)  # 외부 브라우저로 접속해야 하기 때문에 외부링크 허용 True, 허용하지 않으면 False

        self.clear_btn = QPushButton('Clear')  # 버튼 생성(버튼에 쓰일 값은 Clear)
        self.clear_btn.pressed.connect(
            self.clear_text)  # 버튼이 눌려지면 clear_text 함수 호출

        vbox = QVBoxLayout()  # 박스 객체 생성
        vbox.addWidget(self.le, 0)  # 0행에 위젯 달기
        vbox.addWidget(self.tb, 1)  # 1행에 위젯 달기
        vbox.addWidget(self.clear_btn, 2)  # 2행에 버튼 달기

        self.setLayout(vbox)

        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 300)
        self.show()

    def append_text(self):  #텍스트 브라우저에 추가시킬 함수
        text = self.le.text()  # 입력받은 self의 text값을 얻어내서 text 변수에 저장
        self.tb.append(text)  # 텍스트박스에 append 시킨다.(text값을 append)
        self.le.clear()  # 라인 데이터에 쓰여진 있는 값은 클리어시킨다.

    def clear_text(self):  # 버튼눌렀을 때 모두 clear해줄 함수
        self.tb.clear()  # tb, le 모두, te 에도 clear 함수가 있다.
class 확장된글편집기(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.line_edit = QLineEdit()
        self.line_edit.returnPressed.connect(self.addText)

        self.btn_add = QPushButton('입력')
        self.btn_add.clicked.connect(self.addText)

        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)
        self.tb.append('일반 플래인 텍스트입니다.')

        self.tb.setAlignment(Qt.AlignCenter)
        self.btn_clear = QPushButton('지우기')
        self.btn_clear.clicked.connect(self.clearText)

        vbox = QVBoxLayout()
        vbox.addWidget(self.line_edit)
        vbox.addWidget(self.tb)
        vbox.addWidget(self.btn_add)
        vbox.addWidget(self.btn_clear)

        self.setLayout(vbox)

        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 400)
        self.show()

    def addText(self):
        text = self.line_edit.text()
        self.tb.append(text)
        self.line_edit.clear()

    def clearText(self):
        self.tb.clear()
Пример #26
0
class PythonLyrics(QWidget):
    def __init__(self):

        super(PythonLyrics, self).__init__()
        self.lyrics = Lyrics()
        self.init_ui()

    def init_ui(self):

        self.text = QTextBrowser(self)
        self.text.setText(self.lyrics.get_lyrics())
        self.text.setLineWrapMode(QTextBrowser.NoWrap)
        self.text.setReadOnly(True)
        self.text.setOpenExternalLinks(True)

        self.info = QLabel(self)
        self.info.setText(self.lyrics.get_artist() + ' ' +
                          self.lyrics.get_song())

        vbox = QVBoxLayout()
        vbox.addWidget(self.info)
        vbox.addWidget(self.text)

        self.setWindowTitle('PythonLyrics')
        self.setGeometry(700, 200, 605, 700)

        self.setLayout(vbox)

        self.show()

    def refresh(self):
        if self.lyrics.update():
            self.text.clear()
            self.text.setText(self.lyrics.get_lyrics())
            self.info.clear()
            self.info.setText(self.lyrics.get_artist() + ' ' +
                              self.lyrics.get_song())
Пример #27
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.le = QLineEdit()  #태그포함 한줄 입력 받기위한 매머드
        self.le.returnPressed.connect(self.append_text)
        # 엔터키를 눌렀을때(returnPressed) 함수 호출 및 값 자동 전달

        self.tb = QTextBrowser()  #html 해석할수 있는 객체 생성
        self.tb.setAcceptRichText(True)  #글자들을 접근 가능하게 서식있는 텍스트 (RichText) 를 사용
        self.tb.setOpenExternalLinks(True)  #링크를 눌렀을떄 외부와 연결되야 하기때문에 True

        self.clear_btn = QPushButton('Clear')  # 클릭했을때 목록을 다 지워주기 위한 버튼 생성
        self.clear_btn.pressed.connect(self.clear_text)
        # 버튼이 눌려지면 clear_text함수 호출

        vbox = QVBoxLayout()  # 한줄씩 차곡차곡 내려주기 위해 VBoxLayout 객체 생성
        vbox.addWidget(self.le, 0)  # addWidget만 쓰면 하나씩 차곡차곡 쌓이는데
        vbox.addWidget(self.tb, 1)  # 2번쨰 인자로 위치값을 수동으로 지정 해 줄 수 도 있다.
        vbox.addWidget(self.clear_btn, 2)

        self.setLayout(vbox)

        self.setWindowTitle('QTextBrowser')
        self.setGeometry(300, 300, 300, 300)
        self.show()

    def append_text(self):  #한줄 입력을 하면 텍스트 브라우저에 보여주고 라인은 지운다.
        text = self.le.text()
        self.tb.append(text)
        self.le.clear()  #.clear() 은 TestLine, TextBorwser, TextEdit 모두 있다.

    def clear_text(self):  #버튼 클릭했을때 텍스트 브라우저에있는 입력값 초기화
        self.tb.clear()
Пример #28
0
class Widget(QWidget):
    def __init__(self, panel):
        super(Widget, self).__init__(panel)

        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.setSpacing(0)

        self.searchEntry = SearchLineEdit()
        self.treeView = QTreeView(contextMenuPolicy=Qt.CustomContextMenu)
        self.textView = QTextBrowser()

        applyButton = QToolButton(autoRaise=True)
        editButton = QToolButton(autoRaise=True)
        addButton = QToolButton(autoRaise=True)
        self.menuButton = QPushButton(flat=True)
        menu = QMenu(self.menuButton)
        self.menuButton.setMenu(menu)

        splitter = QSplitter(Qt.Vertical)
        top = QHBoxLayout()
        layout.addLayout(top)
        splitter.addWidget(self.treeView)
        splitter.addWidget(self.textView)
        layout.addWidget(splitter)
        splitter.setSizes([200, 100])
        splitter.setCollapsible(0, False)

        top.addWidget(self.searchEntry)
        top.addWidget(applyButton)
        top.addSpacing(10)
        top.addWidget(addButton)
        top.addWidget(editButton)
        top.addWidget(self.menuButton)

        # action generator for actions added to search entry
        def act(slot, icon=None):
            a = QAction(self, triggered=slot)
            self.addAction(a)
            a.setShortcutContext(Qt.WidgetWithChildrenShortcut)
            icon and a.setIcon(icons.get(icon))
            return a

        # hide if ESC pressed in lineedit
        a = act(self.slotEscapePressed)
        a.setShortcut(QKeySequence(Qt.Key_Escape))

        # import action
        a = self.importAction = act(self.slotImport, 'document-open')
        menu.addAction(a)

        # export action
        a = self.exportAction = act(self.slotExport, 'document-save-as')
        menu.addAction(a)

        # apply button
        a = self.applyAction = act(self.slotApply, 'edit-paste')
        applyButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)

        # add button
        a = self.addAction_ = act(self.slotAdd, 'list-add')
        a.setShortcut(QKeySequence(Qt.Key_Insert))
        addButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)

        # edit button
        a = self.editAction = act(self.slotEdit, 'document-edit')
        a.setShortcut(QKeySequence(Qt.Key_F2))
        editButton.setDefaultAction(a)
        menu.addAction(a)

        # set shortcut action
        a = self.shortcutAction = act(
            self.slotShortcut, 'preferences-desktop-keyboard-shortcuts')
        menu.addAction(a)

        # delete action
        a = self.deleteAction = act(self.slotDelete, 'list-remove')
        a.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Delete))
        menu.addAction(a)

        # restore action
        a = self.restoreAction = act(self.slotRestore)
        menu.addSeparator()
        menu.addAction(a)

        # help button
        a = self.helpAction = act(self.slotHelp, 'help-contents')
        menu.addSeparator()
        menu.addAction(a)

        self.treeView.setSelectionBehavior(QTreeView.SelectRows)
        self.treeView.setSelectionMode(QTreeView.ExtendedSelection)
        self.treeView.setRootIsDecorated(False)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setModel(model.model())
        self.treeView.setCurrentIndex(QModelIndex())

        # signals
        self.searchEntry.returnPressed.connect(self.slotReturnPressed)
        self.searchEntry.textChanged.connect(self.updateFilter)
        self.treeView.doubleClicked.connect(self.slotDoubleClicked)
        self.treeView.customContextMenuRequested.connect(self.showContextMenu)
        self.treeView.selectionModel().currentChanged.connect(self.updateText)
        self.treeView.model().dataChanged.connect(self.updateFilter)

        # highlight text
        self.highlighter = highlight.Highlighter(self.textView.document())

        # complete on snippet variables
        self.searchEntry.setCompleter(
            QCompleter([
                ':icon', ':indent', ':menu', ':name', ':python', ':selection',
                ':set', ':symbol', ':template', ':template-run'
            ], self.searchEntry))
        self.readSettings()
        app.settingsChanged.connect(self.readSettings)
        app.translateUI(self)
        self.updateColumnSizes()
        self.setAcceptDrops(True)

    def dropEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            filename = ev.mimeData().urls()[0].toLocalFile()
            if filename:
                ev.accept()
                from . import import_export
                import_export.load(filename, self)

    def dragEnterEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            ev.accept()

    def translateUI(self):
        try:
            self.searchEntry.setPlaceholderText(_("Search..."))
        except AttributeError:
            pass  # not in Qt 4.6
        shortcut = lambda a: a.shortcut().toString(QKeySequence.NativeText)
        self.menuButton.setText(_("&Menu"))
        self.addAction_.setText(_("&Add..."))
        self.addAction_.setToolTip(
            _("Add a new snippet. ({key})").format(
                key=shortcut(self.addAction_)))
        self.editAction.setText(_("&Edit..."))
        self.editAction.setToolTip(
            _("Edit the current snippet. ({key})").format(
                key=shortcut(self.editAction)))
        self.shortcutAction.setText(_("Configure Keyboard &Shortcut..."))
        self.deleteAction.setText(_("&Remove"))
        self.deleteAction.setToolTip(_("Remove the selected snippets."))
        self.applyAction.setText(_("A&pply"))
        self.applyAction.setToolTip(_("Apply the current snippet."))
        self.importAction.setText(_("&Import..."))
        self.importAction.setToolTip(_("Import snippets from a file."))
        self.exportAction.setText(_("E&xport..."))
        self.exportAction.setToolTip(_("Export snippets to a file."))
        self.restoreAction.setText(_("Restore &Built-in Snippets..."))
        self.restoreAction.setToolTip(
            _("Restore deleted or changed built-in snippets."))
        self.helpAction.setText(_("&Help"))
        self.searchEntry.setToolTip(
            _("Enter text to search in the snippets list.\n"
              "See \"What's This\" for more information."))
        self.searchEntry.setWhatsThis(''.join(
            map("<p>{0}</p>\n".format, (
                _("Enter text to search in the snippets list, and "
                  "press Enter to apply the currently selected snippet."),
                _("If the search text fully matches the value of the '{name}' variable "
                  "of a snippet, that snippet is selected.").format(
                      name="name"),
                _("If the search text starts with a colon ':', the rest of the "
                  "search text filters snippets that define the given variable. "
                  "After a space a value can also be entered, snippets will then "
                  "match if the value of the given variable contains the text after "
                  "the space."),
                _("E.g. entering {menu} will show all snippets that are displayed "
                  "in the insert menu.").format(menu="<code>:menu</code>"),
            ))))

    def sizeHint(self):
        return self.parent().mainwindow().size() / 4

    def readSettings(self):
        data = textformats.formatData('editor')
        self.textView.setFont(data.font)
        self.textView.setPalette(data.palette())

    def showContextMenu(self, pos):
        """Called when the user right-clicks the tree view."""
        self.menuButton.menu().popup(self.treeView.viewport().mapToGlobal(pos))

    def slotReturnPressed(self):
        """Called when the user presses Return in the search entry. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)
            self.parent().hide()  # make configurable?
            view.setFocus()

    def slotEscapePressed(self):
        """Called when the user presses ESC in the search entry. Hides the panel."""
        self.parent().hide()
        self.parent().mainwindow().currentView().setFocus()

    def slotDoubleClicked(self, index):
        name = self.treeView.model().name(index)
        view = self.parent().mainwindow().currentView()
        insert.insert(name, view)

    def slotAdd(self):
        """Called when the user wants to add a new snippet."""
        edit.Edit(self, None)

    def slotEdit(self):
        """Called when the user wants to edit a snippet."""
        name = self.currentSnippet()
        if name:
            edit.Edit(self, name)

    def slotShortcut(self):
        """Called when the user selects the Configure Shortcut action."""
        from widgets import shortcuteditdialog
        name = self.currentSnippet()
        if name:
            collection = self.parent().snippetActions
            action = actions.action(name, None, collection)
            default = collection.defaults().get(name)
            mgr = actioncollectionmanager.manager(self.parent().mainwindow())
            cb = mgr.findShortcutConflict
            dlg = shortcuteditdialog.ShortcutEditDialog(
                self, cb, (collection, name))

            if dlg.editAction(action, default):
                mgr.removeShortcuts(action.shortcuts())
                collection.setShortcuts(name, action.shortcuts())
                self.treeView.update()

    def slotDelete(self):
        """Called when the user wants to delete the selected rows."""
        rows = sorted(set(i.row() for i in self.treeView.selectedIndexes()),
                      reverse=True)
        if rows:
            for row in rows:
                name = self.treeView.model().names()[row]
                self.parent().snippetActions.setShortcuts(name, [])
                self.treeView.model().removeRow(row)
            self.updateFilter()

    def slotApply(self):
        """Called when the user clicks the apply button. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)

    def slotImport(self):
        """Called when the user activates the import action."""
        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"),
                                                  _("All Files"))
        caption = app.caption(_("dialog title", "Import Snippets"))
        filename = None
        filename = QFileDialog.getOpenFileName(self, caption, filename,
                                               filetypes)[0]
        if filename:
            from . import import_export
            import_export.load(filename, self)

    def slotExport(self):
        """Called when the user activates the export action."""
        allrows = [
            row for row in range(model.model().rowCount())
            if not self.treeView.isRowHidden(row, QModelIndex())
        ]
        selectedrows = [
            i.row() for i in self.treeView.selectedIndexes()
            if i.column() == 0 and i.row() in allrows
        ]
        names = self.treeView.model().names()
        names = [names[row] for row in selectedrows or allrows]

        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"),
                                                  _("All Files"))
        n = len(names)
        caption = app.caption(
            _("dialog title", "Export {num} Snippet", "Export {num} Snippets",
              n).format(num=n))
        filename = QFileDialog.getSaveFileName(self, caption, None,
                                               filetypes)[0]
        if filename:
            from . import import_export
            try:
                import_export.save(names, filename)
            except (IOError, OSError) as e:
                QMessageBox.critical(
                    self, _("Error"),
                    _("Can't write to destination:\n\n{url}\n\n{error}").
                    format(url=filename, error=e.strerror))

    def slotRestore(self):
        """Called when the user activates the Restore action."""
        from . import restore
        dlg = restore.RestoreDialog(self)
        dlg.setWindowModality(Qt.WindowModal)
        dlg.populate()
        dlg.show()
        dlg.finished.connect(dlg.deleteLater)

    def slotHelp(self):
        """Called when the user clicks the small help button."""
        userguide.show("snippets")

    def currentSnippet(self):
        """Returns the name of the current snippet if it is visible."""
        row = self.treeView.currentIndex().row()
        if row != -1 and not self.treeView.isRowHidden(row, QModelIndex()):
            return self.treeView.model().names()[row]

    def updateFilter(self):
        """Called when the text in the entry changes, updates search results."""
        text = self.searchEntry.text()
        ltext = text.lower()
        filterVars = text.startswith(':')
        if filterVars:
            try:
                fvar, fval = text[1:].split(None, 1)
                fhide = lambda v: v.get(fvar) in (True, None
                                                  ) or fval not in v.get(fvar)
            except ValueError:
                fvar = text[1:].strip()
                fhide = lambda v: not v.get(fvar)
        for row in range(self.treeView.model().rowCount()):
            name = self.treeView.model().names()[row]
            nameid = snippets.get(name).variables.get('name', '')
            if filterVars:
                hide = fhide(snippets.get(name).variables)
            elif nameid == text:
                i = self.treeView.model().createIndex(row, 0)
                self.treeView.selectionModel().setCurrentIndex(
                    i, QItemSelectionModel.SelectCurrent
                    | QItemSelectionModel.Rows)
                hide = False
            elif nameid.lower().startswith(ltext):
                hide = False
            elif ltext in snippets.title(name).lower():
                hide = False
            else:
                hide = True
            self.treeView.setRowHidden(row, QModelIndex(), hide)
        self.updateText()

    def updateText(self):
        """Called when the current snippet changes."""
        name = self.currentSnippet()
        self.textView.clear()
        if name:
            s = snippets.get(name)
            self.highlighter.setPython('python' in s.variables)
            self.textView.setPlainText(s.text)

    def updateColumnSizes(self):
        self.treeView.resizeColumnToContents(0)
        self.treeView.resizeColumnToContents(1)
Пример #29
0
class DY(QTabWidget):
    def __init__(self, parent = None):
        super(DY, self).__init__(parent)
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        
        self.addTab(self.tab1,"Indeed Search")
        self.addTab(self.tab2,"Bookmarked")
        
        self.searchtab()
        self.bookmarktab()
        
        self.setWindowTitle("Job Crawler")
        self.setGeometry(100, 100, 800, 800)
        self.show()
        
              
    def searchtab(self):
        layout = QGridLayout()
        self.enter = QLineEdit()
        self.enter.setPlaceholderText('Enter the Search Word')
        self.enter.returnPressed.connect(self.crawl_indeed)
        
        self.cb = QComboBox()
        self.cb.addItem('See All')
        self.cb.addItem('Internship')
        self.cb.addItem('Full-time')
        self.cb.addItem('Part-time')
        self.cb.activated[str].connect(self.onActivated)
        
        
        self.button = QPushButton('Serach')
        self.button.clicked.connect(self.crawl_indeed)
        
        self.label = QLabel('')
        self.label.resize(1,1)
        
        self.tb = QTextBrowser()
        self.tb.setAcceptRichText(True)
        self.tb.setOpenExternalLinks(True)
        
        layout.addWidget(self.enter, 0, 0, 1, 3)
        layout.addWidget(self.cb, 0, 3, 1 ,1)
        layout.addWidget(self.button, 0, 4, 1, 1)
        layout.addWidget(self.label, 1, 0, 1, 5)
        layout.addWidget(self.tb, 2, 0, 1, 5)

        self.tab1.setLayout(layout)
        
        
    def onActivated(self, text):
        self.label.setText(text)
        self.label.adjustSize()

    def crawl_indeed(self):
        search_word = self.enter.text()
        search_filter = self.cb.currentText()

        if search_word:
            self.label.setText('Recently Added on Indeed for "' + search_word + '"')
            self.tb.clear()
            
            url_search = 'https://www.indeed.com/jobs?q='
            
            if search_filter == 'See All':
                url = url_search + search_word
            
            elif search_filter == 'Internship':
                url = url_search + search_word + '&jt=internship'
                
            elif search_filter == 'Full-time':
                url = url_search + search_word + '&jt=fulltime'
            
            elif search_filter == 'Part-time':
                url = url_search + search_word + '&jt=parttime'
            
            response = requests.get(url)
            html = response.content
            soup = BeautifulSoup(html, 'html.parser')
            job = soup.select('#resultsCol > div > .title > a')
            comp = soup.select('#resultsCol > div > .sjcl > div > .company')
            loc = soup.select('#resultsCol > div > .sjcl > span')
                              
                                      
            for i in range(len(job)):                
                    title = job[i].text
                    company = comp[i].text
                    loca = loc[i].text
                    self.tb.append(str(i+1) + '. ' + title.strip() + '\n    ' + company.strip() + ', ' + loca.strip() +'\n')
                
                
                
    def bookmarktab(self):
        name = QLabel('Company Name:')
        nameedit = QLineEdit()
        location = QLabel('Location:')
        locedit = QLineEdit()
        note = QLabel('Note:')
        noteedit = QTextEdit()

        vbox = QVBoxLayout()
        vbox.addWidget(name)
        vbox.addWidget(nameedit)
        vbox.addWidget(location)
        vbox.addWidget(locedit)
        vbox.addWidget(note)
        vbox.addWidget(noteedit)
        vbox.addStretch()

        self.tab2.setLayout(vbox)
class DocumentationViewerWidget(QWidget):
    """
    Class implementing a rich text documentation viewer.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(DocumentationViewerWidget, self).__init__(parent)
        self.setObjectName("DocumentationViewerWidget")

        self.__verticalLayout = QVBoxLayout(self)
        self.__verticalLayout.setObjectName("verticalLayout")
        self.__verticalLayout.setContentsMargins(0, 0, 0, 0)

        try:
            from PyQt5.QtWebEngineWidgets import (QWebEngineView,
                                                  QWebEngineSettings)
            self.__contents = QWebEngineView(self)
            self.__contents.page().linkHovered.connect(self.__showLink)
            try:
                self.__contents.settings().setAttribute(
                    QWebEngineSettings.FocusOnNavigationEnabled, False)
            except AttributeError:
                # pre Qt 5.8
                pass
            self.__viewerType = "QWebEngineView"
        except ImportError:
            self.__contents = QTextBrowser(self)
            self.__contents.setOpenExternalLinks(True)
            self.__viewerType = "QTextEdit"

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.__contents.sizePolicy().hasHeightForWidth())
        self.__contents.setSizePolicy(sizePolicy)
        self.__contents.setContextMenuPolicy(Qt.NoContextMenu)
        if self.__viewerType != "QTextEdit":
            self.__contents.setUrl(QUrl("about:blank"))
        self.__verticalLayout.addWidget(self.__contents)

        self.__searchWidget = E5TextEditSearchWidget(self, False)
        self.__searchWidget.setFocusPolicy(Qt.WheelFocus)
        self.__searchWidget.setObjectName("searchWidget")
        self.__verticalLayout.addWidget(self.__searchWidget)

        self.__searchWidget.attachTextEdit(self.__contents, self.__viewerType)

    @pyqtSlot(str)
    def __showLink(self, urlStr):
        """
        Private slot to show the hovered link in a tooltip.
        
        @param urlStr hovered URL
        @type str
        """
        QToolTip.showText(QCursor.pos(), urlStr, self.__contents)

    def setHtml(self, html):
        """
        Public method to set the HTML text of the widget.
        
        @param html HTML text to be shown
        @type str
        """
        self.__contents.setEnabled(False)
        self.__contents.setHtml(html)
        self.__contents.setEnabled(True)

    def clear(self):
        """
        Public method to clear the shown contents.
        """
        if self.__viewerType == "QTextEdit":
            self.__contents.clear()
        else:
            self.__contents.setHtml("")
Пример #31
0
class ConsoleWindow(QMainWindow):
    global textEdit

    def __init__(self, parent=None):
        super(ConsoleWindow, self).__init__(parent)
        self.isConUrl = False

        # 上
        self.searchButton = QLineEdit()
        self.searchButton.setPlaceholderText("搜索")
        self.searchButton.setMaximumWidth(300)
        self.searchButton.setMaximumHeight(32)
        self.searchButton.setSizePolicy(QSizePolicy.Maximum,
                                        QSizePolicy.Minimum)

        self.combo = QComboBox(self)
        self.combo.insertItem(0, 'Error')
        self.combo.insertItem(1, 'Debug')
        self.combo.insertItem(2, 'Verbose')
        self.combo.insertItem(3, 'Warning')
        self.combo.setCurrentIndex(0)

        layout_top = QHBoxLayout()
        layout_top.setAlignment(Qt.AlignRight)
        layout_top.setSpacing(20)
        # layout_top.addWidget(self.combo)
        # layout_top.addWidget(self.searchButton)

        self.functionTabWiget = QWidget()
        self.functionTabWiget.setAutoFillBackground(True)
        self.functionTabWiget.setFixedHeight(20)
        self.functionTabWiget.setLayout(layout_top)

        # 左
        self.clearButton = QPushButton(self)
        icon = QIcon(IconTool.buildQIcon('clear.png'))
        self.clearButton.setIcon(icon)
        self.clearButton.setFixedWidth(18)
        self.clearButton.setFixedHeight(20)
        self.clearButton.clicked.connect(self.clear)
        self.clearButton.setToolTip("Clear the logcat")
        self.setStyleSheet('''
            QPushButton{
                border: none;
                background-color: #0000 ;
            }
            
            QPushButton:hover {
            border: 1px solid #C0C0C0;
            background-color: yellow;
            border-style: inset;
            border-radius:2px;
            background-color:#C0C0C0;  
            border-style: solid;
            }
            ''')

        self.layoutLeft = QVBoxLayout()
        self.layoutLeft.setAlignment(Qt.AlignTop)
        self.layoutLeft.setSpacing(1)
        self.layoutLeft.addWidget(self.clearButton)
        self.layoutLeft.setContentsMargins(4, 0, 0, 0)
        self.leftWiget = QWidget()
        self.leftWiget.setAutoFillBackground(True)
        self.leftWiget.setLayout(self.layoutLeft)
        self.leftWiget.setFixedWidth(22)

        # 右
        self.textEdit = QTextBrowser()
        self.textEdit.setOpenLinks(True)
        self.textEdit.setOpenExternalLinks(True)
        self.textEdit.setReadOnly(True)

        self.rightWiget = QWidget()
        self.rightWiget.setAutoFillBackground(True)
        self.rightWiget.setFixedWidth(15)

        self.messageSplitter = QSplitter(Qt.Horizontal)
        self.messageSplitter.addWidget(self.leftWiget)
        self.messageSplitter.addWidget(self.textEdit)
        self.messageSplitter.addWidget(self.rightWiget)

        self.mainSplitter = QSplitter(Qt.Vertical)
        self.mainSplitter.addWidget(self.functionTabWiget)
        self.mainSplitter.addWidget(self.messageSplitter)
        self.setCentralWidget(self.mainSplitter)

        # 重定向输出
        sys.stdout = ConsoleEmittor(textWritten=self.normalOutputWritten)
        sys.stderr = ConsoleEmittor(textWritten=self.normalOutputWritten)

    def normalOutputWritten(self, text):
        cursor = self.textEdit.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertHtml(text)
        self.textEdit.setTextCursor(cursor)
        self.textEdit.ensureCursorVisible()

    def initMenuBar(self):
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('Logcat')
        showLogAction = QAction('Show Log', self)
        fileMenu.addAction(showLogAction)

        helpMenu = menuBar.addMenu('Setting')
        aboutAction = QAction(IconTool.buildQIcon('setting.png'), 'About',
                              self)
        helpMenu.addAction(aboutAction)

    def clear(self):
        self.textEdit.clear()
        return
Пример #32
0
class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
#        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
#        self.setAttribute(Qt.WA_TranslucentBackground)
        self.resize(900, 700)
        self.__search_mode = {'fuzzy':   'fuzzy_search',
                              'precise': 'precise_search',
                              'reg':     'reg_search'}
        # self.__pbn_switch_view = None

        # 创建窗口部件
        self.__widget_frame = QLabel()

        # window title
        self.__lab_title_fram = QLabel()
        self.__lab_title = QLabel('搜索辅助工具')
        self.__lab_title.setAlignment(Qt.AlignCenter)

        self.__lab_open_tool = QLabel('打开文件方式')
        self.__ln_open_tool = QLineEdit()
        self.__pbn_open_tool = QToolButton()
        self.__pbn_open_tool.setText('选择...')
        self.__ln_open_tool.setFixedHeight(20)
        self.__ln_open_tool.setFixedWidth(150)
        self.__pbn_open_tool.setFixedSize(48, 20)
        self.__lab_title_fram.setFixedHeight(50)

        # search mode
        self.__lab_mode_fram = QLabel()
        self.__rbn_fuzzy = QRadioButton('模糊搜索')
        self.__rbn_precise = QRadioButton('精确搜索')
        self.__rbn_reg = QRadioButton('正则表达式搜索')
        self.__rbn_fuzzy.setChecked(True)
        self.__lab_mode_fram.setFixedHeight(22)

        # search pattern
        self.__lab_pattern_fram = QLabel()
        self.__ln_file_name = QLineEdit()
        self.__ln_file_name.setPlaceholderText('请输入搜索条件或正则表达式......')
        self.__rbn_reg_Iyes = QRadioButton('区分大小写')
        self.__rbn_reg_Ino = QRadioButton('不区分大小写')
        self.__lab_pattern_fram.setFixedHeight(20)

        # search path
        self.__lab_path_fram = QLabel()
        self.__ln_file_path = QLineEdit()
        self.__ln_file_path.setPlaceholderText('请选择或输入路径......')
        self.__pbn_file_path = QToolButton()
        self.__pbn_file_path.setText('浏览...')
        self.__rbn_search_file = QRadioButton('检索文件名')
        self.__rbn_search_content = QRadioButton('检索文件内容')
        self.__pbn_file_path.setFixedSize(48, 20)
        self.__lab_path_fram.setFixedHeight(20)

        # search state
        self.__lab_state_fram = QLabel()
        self.__lab_state = QLabel('状态:暂无搜索结果!')
        self.__pbn_search = QPushButton('开始')
        self.__pbn_stop = QPushButton('停止')
        self.__pbn_search.setFixedWidth(89)
        self.__pbn_stop.setFixedWidth(89)
        self.__lab_state_fram.setFixedHeight(35)

        # search result
        self.__tabView = QTabWidget()
        self.__browser_result = QListWidget()
        self.__browser_error = QTextBrowser()
        self.__tabView.addTab(self.__browser_result, '匹配结果')
        self.__tabView.addTab(self.__browser_error, '错误结果')

        self.__btn_group_type = QButtonGroup()
        self.__btn_group_type.addButton(self.__rbn_search_file)
        self.__btn_group_type.addButton(self.__rbn_search_content)
        self.__rbn_search_file.setChecked(True)

        # radiobutton group
        self.__btn_group_re_I = QButtonGroup()
        self.__btn_group_re_I.addButton(self.__rbn_reg_Iyes)
        self.__btn_group_re_I.addButton(self.__rbn_reg_Ino)
        self.__rbn_reg_Iyes.setChecked(True)

        # lines
        '''
        self.__line_1 = QFrame()
        self.__line_1.setFrameStyle(QFrame.HLine | QFrame.Sunken)
        '''

        # 布局
        # open tool
        self.__layout_tool_choose = QHBoxLayout()
        self.__layout_tool_choose.addWidget(self.__ln_open_tool)
        self.__layout_tool_choose.addWidget(self.__pbn_open_tool)
        self.__layout_tool_choose.setSpacing(0)
        self.__layout_tool_choose.setContentsMargins(0, 0, 0, 0)
        
        self.__layout_open_tool = QHBoxLayout()
        self.__layout_open_tool.addWidget(self.__lab_open_tool)
        self.__layout_open_tool.addLayout(self.__layout_tool_choose)
        self.__layout_open_tool.setSpacing(2)

        # window title
        self.__layout_title = QHBoxLayout()
        self.__layout_title.addStretch(5)
        self.__layout_title.addWidget(self.__lab_title)
        self.__layout_title.addStretch(1)
        self.__layout_title.addLayout(self.__layout_open_tool)
        self.__layout_title.setContentsMargins(0, 0, 0, 20)
        self.__lab_title_fram.setLayout(self.__layout_title)

        # search mode
        self.__layout_search_mode = QHBoxLayout()
        self.__layout_search_mode.addWidget(self.__rbn_fuzzy)
        self.__layout_search_mode.addStretch()
        self.__layout_search_mode.addWidget(self.__rbn_precise)
        self.__layout_search_mode.addStretch()
        self.__layout_search_mode.addWidget(self.__rbn_reg)
        self.__layout_search_mode.setContentsMargins(60, 0, 60, 0)
        self.__lab_mode_fram.setLayout(self.__layout_search_mode)

        # search pattern
        self.__layout_search_reg_I = QHBoxLayout()
        self.__layout_search_reg_I.addWidget(self.__rbn_reg_Iyes)
        self.__layout_search_reg_I.addWidget(self.__rbn_reg_Ino)

        self.__layout_pattern = QHBoxLayout()
        self.__layout_pattern.addWidget(self.__ln_file_name)
        self.__layout_pattern.addLayout(self.__layout_search_reg_I)
        self.__layout_pattern.setContentsMargins(0, 0, 0, 0)
        self.__lab_pattern_fram.setLayout(self.__layout_pattern)

        # search path
        self.__layout_choose_path = QHBoxLayout()
        self.__layout_choose_path.addWidget(self.__ln_file_path)
        self.__layout_choose_path.addWidget(self.__pbn_file_path)
        self.__layout_choose_path.setSpacing(0)

        self.__layout_path = QHBoxLayout()
        self.__layout_path.addLayout(self.__layout_choose_path)
        self.__layout_path.addWidget(self.__rbn_search_file)
        self.__layout_path.addWidget(self.__rbn_search_content)
        self.__layout_path.setContentsMargins(0, 0, 0, 0)
        self.__lab_path_fram.setLayout(self.__layout_path)

        # search state
        self.__layout_state = QHBoxLayout()
        self.__layout_state.addWidget(self.__lab_state)
        self.__layout_state.addWidget(self.__pbn_search)
        self.__layout_state.addWidget(self.__pbn_stop)
        self.__layout_state.setContentsMargins(0, 0, 0, 10)
        self.__lab_state_fram.setLayout(self.__layout_state)

        # top layout
        self.__layout_top = QVBoxLayout()
        self.__layout_top.addWidget(self.__lab_title_fram)
        self.__layout_top.addWidget(self.__lab_mode_fram)
        self.__layout_top.addWidget(self.__lab_pattern_fram)
        self.__layout_top.addWidget(self.__lab_path_fram)
        self.__layout_top.addWidget(self.__lab_state_fram)
        self.__layout_top.addWidget(self.__tabView)
        self.__layout_top.setSpacing(10)
        self.__widget_frame.setLayout(self.__layout_top)

        self.__layout_fram = QGridLayout()
        self.__layout_fram.addWidget(self.__widget_frame, 0, 0, 1, 1)
        self.__layout_fram.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.__layout_fram)

        # set object name
        self.__widget_frame.setObjectName('fram')
        self.__lab_title.setObjectName('lab_title')
        self.__ln_open_tool.setObjectName('ln_open_tool')
        self.__lab_mode_fram.setObjectName('mode_fram')
        self.__ln_file_name.setObjectName('ln_pattern')
        self.__ln_file_path.setObjectName('ln_path')
        self.__lab_state.setObjectName('state')
        self.__tabView.setObjectName('tabView')
        self.__browser_result.setObjectName('browser_result')
        self.__browser_error.setObjectName('browser_error')

        self.setStyleSheet(
            '#fram{'
                'border-image: url(Images/bg);'
            '}'
            '#lab_title{'
                'color: white;'
                'font-size: 18pt;'
            '}'
            '#open_tool{'
                'color: black;'
            '}'
            '#mode_fram{'
                # 'border-top: 1px solid rgba(20, 20, 20, 100);'
                # 'border-bottom: 1px solid rgba(20, 20, 20, 100);'
                'background: rgba(0, 0, 0, 40);'
            '}'
            '#ln_open_tool, #ln_path{'
                'border-top-left-radius:    2px;'
                'border-bottom-left-radius: 2px;'
            '}'
            '#ln_pattern{'
                'border-radius: 2px;'
            '}'
            '#state{'
                'background: rgba(0, 0, 0, 40);'
                'border-radius: 2px;'
                'padding: 1px;'
                'color: rgb(240, 240, 240);'
            '}'
            'QTabBar::tab {'
                'border: 0;'
                'width:  90px;'
                'height: 20px;'
                'margin: 0 2px 0 0;'        # top right bottom left
                # 'border-top-left-radius: 5px;'
                # 'border-top-right-radius: 5px;'
                'color: rgb(200, 255, 255;);'
            '}'
            'QTabBar::tab:selected{'
                'background: rgba(25, 0, 0, 40);'
                'border-left: 1px solid rgba(255, 255, 255, 200);'
                'border-top: 1px solid rgba(255, 255, 255, 200);'
                'border-right: 1px solid rgba(255, 255, 255, 200);'
            '}'
            'QTabWidget:pane {'
                'border: 1px solid rgba(255, 255, 255, 200);'
                'background: rgba(0, 0, 0, 80);'
            '}'
            '#browser_result, #browser_error{'
                'background: rgba(0, 0, 0, 0);'
                'border: 0;'
            '}'
            'QLineEdit{'
                'background: rgba(0, 0, 0, 40);'
                'border: 1px solid rgba(220, 220, 220, 200);'
                'color: white;'
                'height: 20px;'
            '}'
            'QPushButton{'
                'background: rgba(0, 0, 0, 100);'
                'border-radius: 5px;'
                'height: 20px;'
                'color: white;'
            '}'
            'QPushButton::hover{'
                'background: rgba(0, 0, 0, 150);'
            '}'
            'QToolButton{'
                'background: rgba(0, 0, 0, 100);'
                'color: white;'
                'border-top-right-radius:    2px;'
                'border-bottom-right-radius: 2px;'
            '}'
            'QToolButton::hover{'
                'background: rgba(0, 0, 0, 150);'
            '}'
            )

        self.__ln_file_name.setFocus()
        self.__pbn_search.setShortcut(Qt.Key_Return)

        # 关联 信号/槽
        self.__pbn_file_path.clicked.connect(self.choose_path)
        self.__pbn_search.clicked.connect(self.pbn_search_clicked)
        self.__pbn_stop.clicked.connect(self.pbn_stop)
        self.__pbn_open_tool.clicked.connect(self.choose_open_tool)
        self.__browser_result.doubleClicked.connect(self.listitem_clicked)

        # 线程间共享数据队列
        queue_size = 10000
        self.__queue_result = Queue(queue_size)
        self.__queue_error = Queue(queue_size)

        # 标记搜索状态
        self.__searching = False

        # 强制结束子线程
        self.__thread_killer = False

    # 重写鼠标按下事件
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.offset = event.globalPos() - self.pos()

    # 重写鼠标移动事件
    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() - self.offset)

    # 检测记事本程序
    def set_open_tool(self):
        if platform.architecture() == ('32bit', 'WindowsPE'):
            possible_dir = ['C:\\Program Files\\Sublime Text 2', 'C:\\Sublime Text 2',
                            'D:\\Program Files\\Sublime Text 2', 'D:\\Sublime Text 2',
                            'E:\\Program Files\\Sublime Text 2', 'E:\\Sublime Text 2',
                            'F:\\Program Files\\Sublime Text 2', 'F:\\Sublime Text 2',
                            'C:\\Program Files\\Notepad++', 'C:\\notepad++',
                            'D:\\Program Files\\Notepad++', 'D:\\notepad++',
                            'E:\\Program Files\\Notepad++', 'E:\\notepad++',
                            'F:\\Program Files\\Notepad++', 'F:\\notepad++',
                            'C:\\Windows\\System32']
        elif platform.architecture() == ('32bit', 'ELF'):
            possible_dir = ['/usr/bin']
        for rootdir in possible_dir:
            for root, dirs, files in walk(rootdir):
                for file in files:
                    if file == 'sublime_text.exe' or file == 'notepad++.exe' or file == 'notepad.exe':
                        self.__ln_open_tool.setText(join(root, file))
                        return
        
    # 搜索文件名
    def search_from_filename(self, filepath, filename, mode='fuzzy_search', I=True):
        # check arguments of searching
        if filepath == '' or not exists(filepath):
            return False
        if mode not in self.__search_mode.values():
            return False
        if filename == '':
            return False

        # count
        count = 0

        # fuzzy mode
        if mode == self.__search_mode['fuzzy']:
            for root, dirs, files in walk(filepath):
                for each_file in files:
                    # kill subThread
                    if self.__thread_killer == True:
                        return
                        
                    if filename in each_file:
                        count += 1
                        self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count)
                        self.__queue_result.put(join(root, each_file))
                        self.__tabView.setTabText(0, '匹配结果(%d)' % count)
        # precise mode
        elif mode == self.__search_mode['precise']:
            for root, dirs, files in walk(filepath):
                for each_file in files:
                    # kill subThread
                    if self.__thread_killer == True:
                        return
                        
                    if filename == splitext(each_file)[0] or filename == each_file:
                        count += 1
                        self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count)
                        self.__queue_result.put(join(root, each_file))
                        self.__tabView.setTabText(0, '匹配结果(%d)' % count)
        # regular expression mode
        elif mode == self.__search_mode['reg']:
            if I:
                pattern = re.compile(r'%s' % filename)
            else:
                pattern = re.compile(r'%s' % filename, re.I)

            for root, dirs, files in walk(filepath):
                for each_file in files:
                    # kill subThread
                    if self.__thread_killer == True:
                        return
                        
                    if re.search(pattern, each_file):
                        count += 1
                        self.__lab_state.setText('正在搜索......已搜到 %d 个文件' % count)
                        self.__queue_result.put(join(root, each_file))
                        self.__tabView.setTabText(0, '匹配结果(%d)' % count)
        self.__lab_state.setText('搜索完毕! 共搜到 %d 个文件' % count)     # finished
        self.__searching = False                # set serching flag

    # 搜索文件内容
    def search_from_content(self, path, content, mode='fuzzy_search', I=True):
        if path == '' or not exists(path):
            return False
        if mode not in self.__search_mode.values():
            return False
        if content == '':
            return False
        pass_file_count = 0
        error_number = 0
        current_file = ''
        processing_file = ''
        match_files_count = 0
        if mode == self.__search_mode['reg']:
            if I:
                pattern = re.compile(r'%s' % content)
            else:
                pattern = re.compile(r'%s' % content, re.I)
            for root, dirs, files in walk(path):
                for each_file in [file for file in files if file.endswith('.h') or file.endswith('.cpp') or file.endswith('.cs')]:
                    current_file = join(root, each_file)
                    pass_file_count += 1
                    self.__lab_state.setText('正在搜索......%s' % current_file)
                    try:
                        for line_number, line in enumerate(open(current_file)):
                            # kill subThread
                            if self.__thread_killer == True:
                                return
                            
                            if re.search(pattern, line):
                                if processing_file != current_file:
                                    self.__queue_result.put('\n%s' % current_file)
                                    processing_file = current_file
                                    match_files_count += 1
                                self.__queue_result.put('line %s: %s' % (line_number, line.strip()))
                    except Exception as error:
                        self.__queue_error.put("%s\n(%s)\n" % (error, current_file))
                        pass_file_count -= 1
                        error_number += 1
                        continue
                    self.__tabView.setTabText(0, '匹配结果(%d)' % match_files_count)
        else:
            for root, dirs, files in walk(path):
                for each_file in [file for file in files if file.endswith('.h') or file.endswith('.cpp') or file.endswith('.cs') or file.endswith('.txt') or file.endswith('.py')]:
                    current_file = join(root, each_file)
                    pass_file_count += 1
                    self.__lab_state.setText('正在搜索......%s' % current_file)
                    try:
                        for line_number, line in enumerate(open(current_file)):
                            # kill subThread
                            if self.__thread_killer == True:
                                return
                            
                            if content in line:                                         # 匹配成功
                                if processing_file != current_file:                     # 如果是新文件
                                    self.__queue_result.put('\n%s' % current_file)      # 文件名入队
                                    processing_file = current_file                      # 更新文件标记
                                    match_files_count += 1
                                self.__queue_result.put('line %s: %s' % (line_number, line.strip()))    # 匹配行入队
                    except Exception as error:
                        self.__queue_error.put("%s\n(%s)\n" % (error, current_file))
                        pass_file_count -= 1
                        error_number += 1
                        continue
                    self.__tabView.setTabText(0, '匹配结果(%d)' % match_files_count)
        # self.__queue_result.put()
        self.__lab_state.setText('搜索完毕!成功匹配 %d 个文件,处理 %s 个文件,失败 %s 文件。' % (match_files_count, pass_file_count, error_number))
        self.__searching = False

    # 单击选择路径按钮
    def choose_path(self):
        path = QFileDialog.getExistingDirectory()
        if path != '':
            path = sep.join(path.split('/'))
            self.__ln_file_path.setText(path)

    # 选择打开文件工具
    def choose_open_tool(self):
        path = QFileDialog.getOpenFileName()
        if path[0] != '':
            self.__ln_open_tool.setText(path[0])

    # 显示搜索结果
    def show_search_result(self):
        """将搜索结果加载到界面,供用户查看和操作"""
        line_block = []         # 定义临时列表,成批加载,避免刷新频率过高造成界面闪烁
        block_size = 10         # 一次性加载的个数
        while self.__searching or self.__queue_result.qsize():
            # kill subThread
            if self.__thread_killer == True:
                return
            
            # if self.__searching or self.__queue_result.qsize() >= block_size:     // 永远记住这个 bug (生产者-消费者 问题)
            if self.__queue_result.qsize() >= block_size:                           # 如果队列中不小于 block_size 个项
                for i in range(block_size):                                             # 取出 block_size 个项
                    line_block.append(self.__queue_result.get())                        # 出队操作
                self.__browser_result.addItems(line_block)                                     # 一次性添加 block_size 个条目
                line_block.clear()                                                      # 清空临时列表
            elif self.__queue_result.qsize() >= 0:                                                                   # 如果队列中小于 block_size 各项
                item = self.__queue_result.get()                                        # 出队一项
                self.__browser_result.addItem(QListWidgetItem(item))                           # 加载到界面
            #self.__browser.setCurrentRow(self.__browser.count()-1)                  # 设置列表中最后一项为当前项,使列表不停滚动
            sleep(0.05)                                                              # 给界面事件循环腾出时间,避免界面冻结
        #self.__pbn_search.setEnabled(True)

    # 显示出错结果
    def show_error_result(self):
        """打印略过的文件和出错原因,多为 I/O Error"""
        count = 0
        while self.__queue_error.qsize() or self.__searching:
            # kill subThread
            if self.__thread_killer == True:
                return
            
            if self.__queue_error.qsize() <= 0:
               continue
            self.__browser_error.append(self.__queue_error.get())
            count += 1
            self.__tabView.setTabText(1, '错误结果(%d)' % count)

    # 单击检索按钮
    def pbn_search_clicked(self):
        """To search allow the arguments from UI"""
        # 获取 UI 数据
        file_path = self.__ln_file_path.text()
        file_name = self.__ln_file_name.text()

        # 检查参数
        if file_path == '':
            QMessageBox(QMessageBox.Warning, '缺少参数!', '请输入搜索路径!', QMessageBox.Ok, self).exec_()
            return
        if file_name == '':
            QMessageBox(QMessageBox.Warning, '缺少参数!', '请输入匹配条件!', QMessageBox.Ok, self).exec_()
            return

        # 判断搜索模式
        mode = self.__search_mode['fuzzy']
        if self.__rbn_reg.isChecked():
            mode = self.__search_mode['reg']
        elif self.__rbn_fuzzy.isChecked():
            mode = self.__search_mode['fuzzy']
        elif self.__rbn_precise.isChecked():
            mode = self.__search_mode['precise']

        # 大小写敏感标记
        I = True
        if self.__rbn_reg_Ino.isChecked():
            I = False

        self.__browser_result.clear()
        self.__browser_error.clear()
        self.__tabView.setTabText(0, '匹配结果(0)')
        self.__tabView.setTabText(1, '错误结果(0)')
        self.__searching = True

        # 开启子线程,后台深度遍历
        self.__thread_killer = False
        if self.__rbn_search_file.isChecked():
            self.__lab_state.setText('正在搜索......已搜索到 0 个文件')
            self.__sub_thread_search = Thread(target=self.search_from_filename, args=(file_path, file_name, mode, I))
            self.__sub_thread_search.start()
        else:
            self.__lab_state.setText('正在搜索......')
            self.__sub_thread_search = Thread(target=self.search_from_content, args=(file_path, file_name, mode, I))
            self.__sub_thread_search.start()

        # 开启子线程,显示搜索结果
        self.__sub_thread_show_result = Thread(target=self.show_search_result)
        self.__sub_thread_show_result.start()

        # 开启子线程,显示错误结果
        self.__sub_thread_show_error = Thread(target=self.show_error_result)
        self.__sub_thread_show_error.start()

        # self.__pbn_search_file.setEnable(False)
        # self.__pbn_search_content.setEnable(False)

    # 单击停止按钮
    def pbn_stop(self):
        if not self.__searching:
            return
        self.__thread_killer = True
        while self.__queue_result.qsize():
            self.__queue_result.get()
        while self.__queue_error.qsize():
            self.__queue_error.get()
        self.__lab_state.setText('搜索已停止!')
        self.__searching = False

    # 双击搜索结果
    def listitem_clicked(self):
        """Double click to open the file from search result"""
        file_path = self.__browser_result.currentItem().text().strip()
        read_tool = self.__ln_open_tool.text()
        if not exists(file_path):
            QMessageBox.warning(self, '错误!', '请双击文件名\n%s 不是文件或打不开!' % file_path, QMessageBox.Ok)
            return
        if splitext(file_path)[1] in ['.jpg', '.png', '.jpeg', '.gif']:
            file_path = r'%s'.replace(' ', r'\ ') % file_path
            system('%s' % file_path)
        else:
            system('"%s" %s' % (read_tool, file_path))
Пример #33
0
class Sansimera(QMainWindow):
    def __init__(self, parent=None):
        super(Sansimera, self).__init__(parent)
        self.settings = QSettings()
        self.timer = QTimer(self)
        self.timer_reminder = QTimer(self)
        self.timer_reminder.timeout.connect(self.reminder_tray)
        interval = self.settings.value('Interval') or '1'
        if interval != '0':
            self.timer_reminder.start(int(interval) * 60 * 60 * 1000)
        self.tentatives = 0
        self.gui()
        self.lista = []
        self.lista_pos = 0
        self.eortazontes_shown = False
        self.eortazontes_names = ''

    def gui(self):
        self.systray = QSystemTrayIcon()
        self.icon = QIcon(':/sansimera.png')
        self.systray.setIcon(self.icon)
        self.systray.setToolTip('Σαν σήμερα...')
        self.menu = QMenu()
        self.exitAction = QAction('&Έξοδος', self)
        self.refreshAction = QAction('&Ανανέωση', self)
        self.aboutAction = QAction('&Σχετικά', self)
        self.notification_interval = QAction('Ει&δοποίηση εορταζόντων', self)
        self.menu.addAction(self.notification_interval)
        self.menu.addAction(self.refreshAction)
        self.menu.addAction(self.aboutAction)
        self.menu.addAction(self.exitAction)
        self.systray.setContextMenu(self.menu)
        self.notification_interval.triggered.connect(self.interval_namedays)
        self.exitAction.triggered.connect(exit)
        self.refreshAction.triggered.connect(self.refresh)
        self.aboutAction.triggered.connect(self.about)
        self.browser = QTextBrowser()
        self.browser.setOpenExternalLinks(True)
        self.setGeometry(600, 500, 400, 300)
        self.setWindowIcon(self.icon)
        self.setWindowTitle('Σαν σήμερα...')
        self.setCentralWidget(self.browser)
        self.systray.show()
        self.systray.activated.connect(self.activate)
        self.browser.append('Λήψη...')
        nicon = QIcon(':/next')
        picon = QIcon(':/previous')
        ricon = QIcon(':/refresh')
        iicon = QIcon(':/info')
        qicon = QIcon(':/exit')
        inicon = QIcon(':/notifications')
        self.nextAction = QAction('Επόμενο', self)
        self.nextAction.setIcon(nicon)
        self.previousAction = QAction('Προηγούμενο', self)
        self.refreshAction.triggered.connect(self.refresh)
        self.nextAction.triggered.connect(self.nextItem)
        self.previousAction.triggered.connect(self.previousItem)
        self.previousAction.setIcon(picon)
        self.refreshAction.setIcon(ricon)
        self.exitAction.setIcon(qicon)
        self.aboutAction.setIcon(iicon)
        self.notification_interval.setIcon(inicon)
        controls = QToolBar()
        self.addToolBar(Qt.BottomToolBarArea, controls)
        controls.setObjectName('Controls')
        controls.addAction(self.previousAction)
        controls.addAction(self.nextAction)
        controls.addAction(self.refreshAction)
        self.restoreState(self.settings.value("MainWindow/State", QByteArray()))
        self.refresh()

    def interval_namedays(self):
        dialog = sansimera_reminder.Reminder(self)
        dialog.applied_signal['QString'].connect(self.reminder)
        if dialog.exec_() == 1:
            print('Apply namedays reminder interval...')

    def reminder(self, time):
        self.settings.setValue('Interval', time)
        if time != '0':
            self.timer_reminder.start(int(time) * 60 * 60 * 1000)
            print('Reminder = ' + time + ' hour(s)')
        else:
            print('Reminder = None')

    def nextItem(self):
        if len(self.lista) >= 1:
            self.browser.clear()
            if self.lista_pos != len(self.lista)-1:
                self.lista_pos += 1
            else:
                self.lista_pos = 0
            self.browser.append(self.lista[self.lista_pos])
            self.browser.moveCursor(QTextCursor.Start)
        else:
            return

    def previousItem(self):
        if len(self.lista) >= 1:
            self.browser.clear()
            if self.lista_pos == 0:
                self.lista_pos = len(self.lista)-1
            else:
                self.lista_pos -= 1
            self.browser.append(self.lista[self.lista_pos])
            self.browser.moveCursor(QTextCursor.Start)
        else:
            return

    def refresh(self):
        try:
            if self.workThread.isRunning():
                return
        except AttributeError:
            pass
        self.menu.hide()
        self.browser.clear()
        self.lista = []
        self.systray.setToolTip('Σαν σήμερα...')
        self.browser.append('Λήψη...')
        self.tentatives = 0
        self.eortazontes_shown = False
        self.download()

    def activate(self, reason):
        self.menu.hide()
        state = self.isVisible()
        if reason == 3:
            if state:
                self.hide()
                return
            else:
                self.show()
                return
        if reason == 1:
            self.menu.hide()
            self.menu.popup(QCursor.pos())

    def download(self):
        self.workThread = WorkThread()
        self.workThread.online_signal[bool].connect(self.status)
        self.workThread.finished.connect(self.window)
        self.workThread.event['QString'].connect(self.addlist)
        self.workThread.names['QString'].connect(self.nameintooltip)
        self.workThread.start()

    def addlist(self, text):
        self.lista.append(text)

    def status(self, status):
        self.status_online = status

    def reminder_tray(self):
        text = self.eortazontes_names.replace('<br/>', '\n')
        urltexts = re.findall('(<a [\S]+php">)', text)
        urltexts.extend(['</a>', '<p>', '<div>'])
        show_notifier_text = text
        for i in urltexts:
            show_notifier_text = show_notifier_text.replace(i, '')
        show_notifier_text = show_notifier_text.replace('\n\n', '\n')
        show_notifier_text = show_notifier_text.replace('www.eortologio.gr)', 'www.eortologio.gr)\n')
        self.systray.showMessage('Εορτάζουν:\n', show_notifier_text)
        self.systray.setToolTip('Εορτάζουν:\n' + show_notifier_text)

    def nameintooltip(self, text):
        self.eortazontes_names = text
        for i in ['<br/>', '<div>']:
            text = text.replace(i, '')
        self.eortazontes_in_window = text
        if self.eortazontes_shown:
            return
        self.reminder_tray()
        self.eortazontes_shown = True

    def window(self):
        self.lista.append('<div class=""></div>' + self.eortazontes_in_window)
        if self.status_online:
            self.browser.clear()
            self.browser.append(self.lista[0])
            self.lista_pos = 0
            return
        else:
            if self.tentatives == 10:
                return
            self.timer.singleShot(5000, self.refresh)
            self.tentatives += 1

    def closeEvent(self, event):
        self.settings.setValue("MainWindow/State", self.saveState())

    def about(self):
        self.menu.hide()
        QMessageBox.about(self, "Εφαρμογή «Σαν σήμερα...»",
                        """<b>sansimera-qt</b> v{0}
                        <p>Δημήτριος Γλενταδάκης <a href="mailto:[email protected]">[email protected]</a>
                        <br/>Ιστοσελίδα: <a href="https://github.com/dglent/sansimera-qt">
                        github sansimera-qt</a>
                        <p>Εφαρμογή πλαισίου συστήματος για την προβολή
                        <br/>των γεγονότων από την ιστοσελίδα <a href="http://www.sansimera.gr">
                        www.sansimera.gr</a><br/>
                        Πηγή εορτολογίου: <a href="http://www.eortologio.gr">
                        www.eortologio.gr</a>, <a href="http://www.synaxari.gr">
                        www.synaxari.gr</a>
                        <p>Άδεια χρήσης: GPLv3 <br/>Python {1} - Qt {2} - PyQt {3} σε {4}""".format(
                        __version__, platform.python_version(),
                        QT_VERSION_STR, PYQT_VERSION_STR, platform.system()))
Пример #34
0
class Widget(QWidget):
    def __init__(self, panel):
        super(Widget, self).__init__(panel)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.setSpacing(0)
        
        self.searchEntry = SearchLineEdit()
        self.treeView = QTreeView(contextMenuPolicy=Qt.CustomContextMenu)
        self.textView = QTextBrowser()
        
        applyButton = QToolButton(autoRaise=True)
        editButton = QToolButton(autoRaise=True)
        addButton = QToolButton(autoRaise=True)
        self.menuButton = QPushButton(flat=True)
        menu = QMenu(self.menuButton)
        self.menuButton.setMenu(menu)
        
        splitter = QSplitter(Qt.Vertical)
        top = QHBoxLayout()
        layout.addLayout(top)
        splitter.addWidget(self.treeView)
        splitter.addWidget(self.textView)
        layout.addWidget(splitter)
        splitter.setSizes([200, 100])
        splitter.setCollapsible(0, False)
        
        top.addWidget(self.searchEntry)
        top.addWidget(applyButton)
        top.addSpacing(10)
        top.addWidget(addButton)
        top.addWidget(editButton)
        top.addWidget(self.menuButton)
        
        # action generator for actions added to search entry
        def act(slot, icon=None):
            a = QAction(self, triggered=slot)
            self.addAction(a)
            a.setShortcutContext(Qt.WidgetWithChildrenShortcut)
            icon and a.setIcon(icons.get(icon))
            return a
        
        # hide if ESC pressed in lineedit
        a = act(self.slotEscapePressed)
        a.setShortcut(QKeySequence(Qt.Key_Escape))
        
        # import action
        a = self.importAction = act(self.slotImport, 'document-open')
        menu.addAction(a)
        
        # export action
        a = self.exportAction = act(self.slotExport, 'document-save-as')
        menu.addAction(a)
        
        # apply button
        a = self.applyAction = act(self.slotApply, 'edit-paste')
        applyButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)
        
        # add button
        a = self.addAction_ = act(self.slotAdd, 'list-add')
        a.setShortcut(QKeySequence(Qt.Key_Insert))
        addButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)
        
        # edit button
        a = self.editAction = act(self.slotEdit, 'document-edit')
        a.setShortcut(QKeySequence(Qt.Key_F2))
        editButton.setDefaultAction(a)
        menu.addAction(a)
        
        # set shortcut action
        a = self.shortcutAction = act(self.slotShortcut, 'preferences-desktop-keyboard-shortcuts')
        menu.addAction(a)
        
        # delete action
        a = self.deleteAction = act(self.slotDelete, 'list-remove')
        a.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Delete))
        menu.addAction(a)
        
        # restore action
        a = self.restoreAction = act(self.slotRestore)
        menu.addSeparator()
        menu.addAction(a)
        
        # help button
        a = self.helpAction = act(self.slotHelp, 'help-contents')
        menu.addSeparator()
        menu.addAction(a)
        
        self.treeView.setSelectionBehavior(QTreeView.SelectRows)
        self.treeView.setSelectionMode(QTreeView.ExtendedSelection)
        self.treeView.setRootIsDecorated(False)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setModel(model.model())
        self.treeView.setCurrentIndex(QModelIndex())
        
        # signals
        self.searchEntry.returnPressed.connect(self.slotReturnPressed)
        self.searchEntry.textChanged.connect(self.updateFilter)
        self.treeView.doubleClicked.connect(self.slotDoubleClicked)
        self.treeView.customContextMenuRequested.connect(self.showContextMenu)
        self.treeView.selectionModel().currentChanged.connect(self.updateText)
        self.treeView.model().dataChanged.connect(self.updateFilter)
        
        # highlight text
        self.highlighter = highlight.Highlighter(self.textView.document())
        
        # complete on snippet variables
        self.searchEntry.setCompleter(QCompleter([
            ':icon', ':indent', ':menu', ':name', ':python', ':selection',
            ':set', ':symbol', ':template', ':template-run'], self.searchEntry))
        self.readSettings()
        app.settingsChanged.connect(self.readSettings)
        app.translateUI(self)
        self.updateColumnSizes()
        self.setAcceptDrops(True)

    def dropEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            filename = ev.mimeData().urls()[0].toLocalFile()
            if filename:
                ev.accept()
                from . import import_export
                import_export.load(filename, self)
        
    def dragEnterEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            ev.accept()
        
    def translateUI(self):
        try:
            self.searchEntry.setPlaceholderText(_("Search..."))
        except AttributeError:
            pass # not in Qt 4.6
        shortcut = lambda a: a.shortcut().toString(QKeySequence.NativeText)
        self.menuButton.setText(_("&Menu"))
        self.addAction_.setText(_("&Add..."))
        self.addAction_.setToolTip(
            _("Add a new snippet. ({key})").format(key=shortcut(self.addAction_)))
        self.editAction.setText(_("&Edit..."))
        self.editAction.setToolTip(
            _("Edit the current snippet. ({key})").format(key=shortcut(self.editAction)))
        self.shortcutAction.setText(_("Configure Keyboard &Shortcut..."))
        self.deleteAction.setText(_("&Remove"))
        self.deleteAction.setToolTip(_("Remove the selected snippets."))
        self.applyAction.setText(_("A&pply"))
        self.applyAction.setToolTip(_("Apply the current snippet."))
        self.importAction.setText(_("&Import..."))
        self.importAction.setToolTip(_("Import snippets from a file."))
        self.exportAction.setText(_("E&xport..."))
        self.exportAction.setToolTip(_("Export snippets to a file."))
        self.restoreAction.setText(_("Restore &Built-in Snippets..."))
        self.restoreAction.setToolTip(
            _("Restore deleted or changed built-in snippets."))
        self.helpAction.setText(_("&Help"))
        self.searchEntry.setToolTip(_(
            "Enter text to search in the snippets list.\n"
            "See \"What's This\" for more information."))
        self.searchEntry.setWhatsThis(''.join(map("<p>{0}</p>\n".format, (
            _("Enter text to search in the snippets list, and "
              "press Enter to apply the currently selected snippet."),
            _("If the search text fully matches the value of the '{name}' variable "
              "of a snippet, that snippet is selected.").format(name="name"),
            _("If the search text starts with a colon ':', the rest of the "
              "search text filters snippets that define the given variable. "
              "After a space a value can also be entered, snippets will then "
              "match if the value of the given variable contains the text after "
              "the space."),
            _("E.g. entering {menu} will show all snippets that are displayed "
              "in the insert menu.").format(menu="<code>:menu</code>"),
            ))))
    
    def sizeHint(self):
        return self.parent().mainwindow().size() / 4
        
    def readSettings(self):
        data = textformats.formatData('editor')
        self.textView.setFont(data.font)
        self.textView.setPalette(data.palette())

    def showContextMenu(self, pos):
        """Called when the user right-clicks the tree view."""
        self.menuButton.menu().popup(self.treeView.viewport().mapToGlobal(pos))
    
    def slotReturnPressed(self):
        """Called when the user presses Return in the search entry. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)
            self.parent().hide() # make configurable?
            view.setFocus()

    def slotEscapePressed(self):
        """Called when the user presses ESC in the search entry. Hides the panel."""
        self.parent().hide()
        self.parent().mainwindow().currentView().setFocus()
    
    def slotDoubleClicked(self, index):
        name = self.treeView.model().name(index)
        view = self.parent().mainwindow().currentView()
        insert.insert(name, view)
        
    def slotAdd(self):
        """Called when the user wants to add a new snippet."""
        edit.Edit(self, None)
        
    def slotEdit(self):
        """Called when the user wants to edit a snippet."""
        name = self.currentSnippet()
        if name:
            edit.Edit(self, name)
        
    def slotShortcut(self):
        """Called when the user selects the Configure Shortcut action."""
        from widgets import shortcuteditdialog
        name = self.currentSnippet()
        if name:
            collection = self.parent().snippetActions
            action = actions.action(name, None, collection)
            default = collection.defaults().get(name)
            mgr = actioncollectionmanager.manager(self.parent().mainwindow())
            cb = mgr.findShortcutConflict
            dlg = shortcuteditdialog.ShortcutEditDialog(self, cb, (collection, name))
            
            if dlg.editAction(action, default):
                mgr.removeShortcuts(action.shortcuts())
                collection.setShortcuts(name, action.shortcuts())
                self.treeView.update()
            
    def slotDelete(self):
        """Called when the user wants to delete the selected rows."""
        rows = sorted(set(i.row() for i in self.treeView.selectedIndexes()), reverse=True)
        if rows:
            for row in rows:
                name = self.treeView.model().names()[row]
                self.parent().snippetActions.setShortcuts(name, [])
                self.treeView.model().removeRow(row)
            self.updateFilter()
    
    def slotApply(self):
        """Called when the user clicks the apply button. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)
    
    def slotImport(self):
        """Called when the user activates the import action."""
        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"), _("All Files"))
        caption = app.caption(_("dialog title", "Import Snippets"))
        filename = None
        filename = QFileDialog.getOpenFileName(self, caption, filename, filetypes)[0]
        if filename:
            from . import import_export
            import_export.load(filename, self)
        
    def slotExport(self):
        """Called when the user activates the export action."""
        allrows = [row for row in range(model.model().rowCount())
                       if not self.treeView.isRowHidden(row, QModelIndex())]
        selectedrows = [i.row() for i in self.treeView.selectedIndexes()
                                if i.column() == 0 and i.row() in allrows]
        names = self.treeView.model().names()
        names = [names[row] for row in selectedrows or allrows]
        
        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"), _("All Files"))
        n = len(names)
        caption = app.caption(_("dialog title",
            "Export {num} Snippet", "Export {num} Snippets", n).format(num=n))
        filename = QFileDialog.getSaveFileName(self, caption, None, filetypes)[0]
        if filename:
            from . import import_export
            try:
                import_export.save(names, filename)
            except (IOError, OSError) as e:
                QMessageBox.critical(self, _("Error"), _(
                    "Can't write to destination:\n\n{url}\n\n{error}").format(
                    url=filename, error=e.strerror))
        
    def slotRestore(self):
        """Called when the user activates the Restore action."""
        from . import restore
        dlg = restore.RestoreDialog(self)
        dlg.setWindowModality(Qt.WindowModal)
        dlg.populate()
        dlg.show()
        dlg.finished.connect(dlg.deleteLater)
        
    def slotHelp(self):
        """Called when the user clicks the small help button."""
        userguide.show("snippets")
        
    def currentSnippet(self):
        """Returns the name of the current snippet if it is visible."""
        row = self.treeView.currentIndex().row()
        if row != -1 and not self.treeView.isRowHidden(row, QModelIndex()):
            return self.treeView.model().names()[row]

    def updateFilter(self):
        """Called when the text in the entry changes, updates search results."""
        text = self.searchEntry.text()
        ltext = text.lower()
        filterVars = text.startswith(':')
        if filterVars:
            try:
                fvar, fval = text[1:].split(None, 1)
                fhide = lambda v: v.get(fvar) in (True, None) or fval not in v.get(fvar)
            except ValueError:
                fvar = text[1:].strip()
                fhide = lambda v: not v.get(fvar)
        for row in range(self.treeView.model().rowCount()):
            name = self.treeView.model().names()[row]
            nameid = snippets.get(name).variables.get('name', '')
            if filterVars:
                hide = fhide(snippets.get(name).variables)
            elif nameid == text:
                i = self.treeView.model().createIndex(row, 0)
                self.treeView.selectionModel().setCurrentIndex(i, QItemSelectionModel.SelectCurrent | QItemSelectionModel.Rows)
                hide = False
            elif nameid.lower().startswith(ltext):
                hide = False
            elif ltext in snippets.title(name).lower():
                hide = False
            else:
                hide = True
            self.treeView.setRowHidden(row, QModelIndex(), hide)
        self.updateText()
            
    def updateText(self):
        """Called when the current snippet changes."""
        name = self.currentSnippet()
        self.textView.clear()
        if name:
            s = snippets.get(name)
            self.highlighter.setPython('python' in s.variables)
            self.textView.setPlainText(s.text)
        
    def updateColumnSizes(self):
        self.treeView.resizeColumnToContents(0)
        self.treeView.resizeColumnToContents(1)
Пример #35
0
class LogWidget(QWidget, MooseWidget):
    """
    A widget that shows the log.

    This ties into mooseutils.message.mooseMessage which will
    emit a signal on mooseutils.message.messageEmitter
    This widget listens to messageEmitter and puts
    the text in the widget.
    Color text is supported.
    """
    def __init__(self, **kwds):
        """
        Constructor.
        """
        super(LogWidget, self).__init__(**kwds)
        self.top_layout = WidgetUtils.addLayout(vertical=True)
        self.setLayout(self.top_layout)
        self.log = QTextBrowser(self)
        self.log.setStyleSheet("QTextBrowser { background: black; color: white; }")
        self.log.setReadOnly(True)
        message.messageEmitter.message.connect(self._write)
        self.button_layout = WidgetUtils.addLayout()
        self.hide_button = WidgetUtils.addButton(self.button_layout, self, "Hide", lambda: self.hide())
        self.clear_button = WidgetUtils.addButton(self.button_layout, self, "Clear", lambda: self.log.clear())
        self.top_layout.addWidget(self.log)
        self.top_layout.addLayout(self.button_layout)
        self.resize(800, 500)

    @pyqtSlot(str, str)
    def _write(self, msg, color):
        """
        This is the slot that will write the message to the widget.

        Inputs:
            msg: The message to write
            color: The color to write the text in.
        """
        if not msg:
            return

        msg = msg.encode('utf-8') # make sure if there are bad characters in the message that we can show them.

        if not color or color == "None":
            color = "white"
        else:
            color = str(color)

        if msg.find("\n") >= 0:
            self.log.insertHtml('<div style="color:%s"><pre><code>%s</code></pre></div><br>' % (color.lower(), escape(msg)))
        else:
            self.log.insertHtml('<div style="color:%s">%s</div><br>' % (color.lower(), escape(msg)))
Пример #36
0
class Dialog(QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        
        self._info = None
        self._text = ''
        self._convertedtext = ''
        self._encoding = None
        self.mainwindow = parent
        
        self.fromVersionLabel = QLabel()
        self.fromVersion = QLineEdit()
        self.reason = QLabel()
        self.toVersionLabel = QLabel()
        self.toVersion = QLineEdit()
        self.lilyChooser = lilychooser.LilyChooser()
        self.messages = QTextBrowser()
        self.diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)
        self.uni_diff = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)
        self.copyCheck = QCheckBox(checked=
            QSettings().value('convert_ly/copy_messages', True, bool))
        self.tabw = QTabWidget()
        
        self.tabw.addTab(self.messages, '')
        self.tabw.addTab(self.diff, '')
        self.tabw.addTab(self.uni_diff, '')
        
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Reset | QDialogButtonBox.Save |
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttons.button(QDialogButtonBox.Ok).clicked    .connect(self.accept)
        self.buttons.rejected.connect(self.reject)
        self.buttons.button(QDialogButtonBox.Reset).clicked.connect(self.run)
        self.buttons.button(QDialogButtonBox.Save).clicked.connect(self.saveFile)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        
        grid = QGridLayout()
        grid.addWidget(self.fromVersionLabel, 0, 0)
        grid.addWidget(self.fromVersion, 0, 1)
        grid.addWidget(self.reason, 0, 2, 1, 3)
        grid.addWidget(self.toVersionLabel, 1, 0)
        grid.addWidget(self.toVersion, 1, 1)
        grid.addWidget(self.lilyChooser, 1, 3, 1, 2)
        
        layout.addLayout(grid)
        layout.addWidget(self.tabw)
        layout.addWidget(self.copyCheck)
        layout.addWidget(widgets.Separator())
        layout.addWidget(self.buttons)
        
        app.translateUI(self)
        qutil.saveDialogSize(self, 'convert_ly/dialog/size', QSize(600, 300))
        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        self.finished.connect(self.saveCopyCheckSetting)
        self.lilyChooser.currentIndexChanged.connect(self.slotLilyPondVersionChanged)
        self.slotLilyPondVersionChanged()
        
    def translateUI(self):
        self.fromVersionLabel.setText(_("From version:"))
        self.toVersionLabel.setText(_("To version:"))
        self.copyCheck.setText(_("Save convert-ly messages in document"))
        self.copyCheck.setToolTip(_(
            "If checked, the messages of convert-ly are appended as a "
            "comment to the end of the document."))
        self.tabw.setTabText(0, _("&Messages"))
        self.tabw.setTabText(1, _("&Changes"))
        self.tabw.setTabText(2, _("&Diff"))
        self.buttons.button(QDialogButtonBox.Reset).setText(_("Run Again"))
        self.buttons.button(QDialogButtonBox.Save).setText(_("Save as file"))
        self.setCaption()
    
    def saveCopyCheckSetting(self):
        QSettings().setValue('convert_ly/copy_messages', self.copyCheck.isChecked())
    
    def readSettings(self):
        font = textformats.formatData('editor').font
        self.diff.setFont(font)
        diffFont = QFont("Monospace")
        diffFont.setStyleHint(QFont.TypeWriter)
        self.uni_diff.setFont(diffFont)
    
    def slotLilyPondVersionChanged(self):
        self.setLilyPondInfo(self.lilyChooser.lilyPondInfo())
    
    def setCaption(self):
        version = self._info and self._info.versionString() or _("<unknown>")
        title = _("Convert-ly from LilyPond {version}").format(version=version)
        self.setWindowTitle(app.caption(title))

    def setLilyPondInfo(self, info):
        self._info = info
        self.setCaption()
        self.toVersion.setText(info.versionString())
        self.setConvertedText()
        self.setDiffText()
        self.messages.clear()
    
    def setConvertedText(self, text=''):
        self._convertedtext = text
        self.buttons.button(QDialogButtonBox.Ok).setEnabled(bool(text))
        if text:
            self.diff.setHtml(htmldiff.htmldiff(
                self._text, text,
                _("Current Document"), _("Converted Document"),
                wrapcolumn=100))
        else:
            self.diff.clear()
            
    def setDiffText(self, text=''):
        if text:
            from_filename = "current"   # TODO: maybe use real filename here
            to_filename = "converted"   # but difflib can choke on non-ascii characters,
                                        # see https://github.com/wbsoft/frescobaldi/issues/674
            difflist = list(difflib.unified_diff(
                    self._text.split('\n'), text.split('\n'), 
                    from_filename, to_filename))
            diffHLstr = self.diffHighl(difflist)
            self.uni_diff.setHtml(diffHLstr)
        else:
            self.uni_diff.clear()
    
    def convertedText(self):
        return self._convertedtext or ''
    
    def setDocument(self, doc):
        v = documentinfo.docinfo(doc).version_string()
        if v:
            self.fromVersion.setText(v)
            self.reason.setText(_("(set in document)"))
        else:
            self.reason.clear()
        self._text = doc.toPlainText()
        self._encoding = doc.encoding() or 'UTF-8'
        self.setConvertedText()
        self.setDiffText()
        
    def run(self):
        """Runs convert-ly (again)."""
        fromVersion = self.fromVersion.text()
        toVersion = self.toVersion.text()
        if not fromVersion or not toVersion:
            self.messages.setPlainText(_(
                "Both 'from' and 'to' versions need to be set."))
            return
        info = self._info
        command = info.toolcommand(info.ly_tool('convert-ly'))
        command += ['-f', fromVersion, '-t', toVersion, '-']
        
        # if the user wants english messages, do it also here: LANGUAGE=C
        env = None
        if os.name == "nt":
            # Python 2.7 subprocess on Windows chokes on unicode in env
            env = util.bytes_environ()
        else:
            env = dict(os.environ)
        if sys.platform.startswith('darwin'):
            try:
                del env['PYTHONHOME']
            except KeyError:
                pass
            try:
                del env['PYTHONPATH']
            except KeyError:
                pass
        if QSettings().value("lilypond_settings/no_translation", False, bool):
            if os.name == "nt":
                # Python 2.7 subprocess on Windows chokes on unicode in env
                env[b'LANGUAGE'] = b'C'
            else:
                env['LANGUAGE'] = 'C'
        
        with qutil.busyCursor():
            try:
                proc = subprocess.Popen(command,
                    env = env,
                    stdin = subprocess.PIPE,
                    stdout = subprocess.PIPE,
                    stderr = subprocess.PIPE)
                out, err = proc.communicate(util.platform_newlines(self._text).encode(self._encoding))
            except OSError as e:
                self.messages.setPlainText(_(
                    "Could not start {convert_ly}:\n\n"
                    "{message}\n").format(convert_ly = command[0], message = e))
                return
            out = util.universal_newlines(out.decode('UTF-8'))
            err = util.universal_newlines(err.decode('UTF-8'))
            self.messages.setPlainText(err)
            self.setConvertedText(out)
            self.setDiffText(out)
            if not out or self._convertedtext == self._text:
                self.messages.append('\n' + _("The document has not been changed."))

    def saveFile(self):
        """Save content in tab as file"""
        tabdata = self.getTabData(self.tabw.currentIndex())
        doc = self.mainwindow.currentDocument()
        orgname = doc.url().toLocalFile()
        filename = os.path.splitext(orgname)[0] + '['+tabdata.filename+']'+'.'+tabdata.ext
        caption = app.caption(_("dialog title", "Save File"))
        filetypes = '{0} (*.txt);;{1} (*.htm);;{2} (*)'.format(_("Text Files"), _("HTML Files"), _("All Files"))
        filename = QFileDialog.getSaveFileName(self.mainwindow, caption, filename, filetypes)[0]
        if not filename:
            return False # cancelled
        with open(filename, 'wb') as f:
            f.write(tabdata.text.encode('utf-8'))

    def getTabData(self, index):
        """Get content of current tab from current index"""
        if index == 0:
            return FileInfo('message', 'txt', self.messages.toPlainText())
        elif index == 1:
            return FileInfo('html-diff', 'html', self.diff.toHtml())
        elif index == 2:
            return FileInfo('uni-diff', 'diff', self.uni_diff.toPlainText())
            
    def diffHighl(self, difflist):
        """Return highlighted version of input."""
        result = []
        for l in difflist:
            if l.startswith('-'):
                s = '<span style="color: red; white-space: pre-wrap;">'
            elif l.startswith('+'):
                s = '<span style="color: green; white-space: pre-wrap;">'
            else:
                s = '<span style="white-space: pre-wrap;">'
            h = l.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            result.append(s + h + '</span>')
        return '<br>'.join(result)
Пример #37
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.selectedDate = QDate.currentDate()
        self.fontSize = 10

        centralWidget = QWidget()

        dateLabel = QLabel("Date:")
        monthCombo = QComboBox()

        for month in range(1, 13):
            monthCombo.addItem(QDate.longMonthName(month))

        yearEdit = QDateTimeEdit()
        yearEdit.setDisplayFormat('yyyy')
        yearEdit.setDateRange(QDate(1753, 1, 1), QDate(8000, 1, 1))

        monthCombo.setCurrentIndex(self.selectedDate.month() - 1)
        yearEdit.setDate(self.selectedDate)

        self.fontSizeLabel = QLabel("Font size:")
        self.fontSizeSpinBox = QSpinBox()
        self.fontSizeSpinBox.setRange(1, 64)
        self.fontSizeSpinBox.setValue(10)

        self.editor = QTextBrowser()
        self.insertCalendar()

        monthCombo.activated.connect(self.setMonth)
        yearEdit.dateChanged.connect(self.setYear)
        self.fontSizeSpinBox.valueChanged.connect(self.setfontSize)

        controlsLayout = QHBoxLayout()
        controlsLayout.addWidget(dateLabel)
        controlsLayout.addWidget(monthCombo)
        controlsLayout.addWidget(yearEdit)
        controlsLayout.addSpacing(24)
        controlsLayout.addWidget(self.fontSizeLabel)
        controlsLayout.addWidget(self.fontSizeSpinBox)
        controlsLayout.addStretch(1)

        centralLayout = QVBoxLayout()
        centralLayout.addLayout(controlsLayout)
        centralLayout.addWidget(self.editor, 1)
        centralWidget.setLayout(centralLayout)

        self.setCentralWidget(centralWidget)

    def insertCalendar(self):
        self.editor.clear()
        cursor = self.editor.textCursor()
        cursor.beginEditBlock()

        date = QDate(self.selectedDate.year(), self.selectedDate.month(), 1)

        tableFormat = QTextTableFormat()
        tableFormat.setAlignment(Qt.AlignHCenter)
        tableFormat.setBackground(QColor('#e0e0e0'))
        tableFormat.setCellPadding(2)
        tableFormat.setCellSpacing(4)
        constraints = [QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14),
                       QTextLength(QTextLength.PercentageLength, 14)]

        tableFormat.setColumnWidthConstraints(constraints)

        table = cursor.insertTable(1, 7, tableFormat)

        frame = cursor.currentFrame()
        frameFormat = frame.frameFormat()
        frameFormat.setBorder(1)
        frame.setFrameFormat(frameFormat)

        format = cursor.charFormat()
        format.setFontPointSize(self.fontSize)

        boldFormat = QTextCharFormat(format)
        boldFormat.setFontWeight(QFont.Bold)

        highlightedFormat = QTextCharFormat(boldFormat)
        highlightedFormat.setBackground(Qt.yellow)

        for weekDay in range(1, 8):
            cell = table.cellAt(0, weekDay-1)
            cellCursor = cell.firstCursorPosition()
            cellCursor.insertText(QDate.longDayName(weekDay), boldFormat)

        table.insertRows(table.rows(), 1)

        while date.month() == self.selectedDate.month():
            weekDay = date.dayOfWeek()
            cell = table.cellAt(table.rows()-1, weekDay-1)
            cellCursor = cell.firstCursorPosition()

            if date == QDate.currentDate():
                cellCursor.insertText(str(date.day()), highlightedFormat)
            else:
                cellCursor.insertText(str(date.day()), format)

            date = date.addDays(1)

            if weekDay == 7 and date.month() == self.selectedDate.month():
                table.insertRows(table.rows(), 1)

        cursor.endEditBlock()

        self.setWindowTitle("Calendar for %s %d" % (QDate.longMonthName(self.selectedDate.month()), self.selectedDate.year()))

    def setfontSize(self, size):
        self.fontSize = size
        self.insertCalendar()

    def setMonth(self, month):
        self.selectedDate = QDate(self.selectedDate.year(), month + 1,
                self.selectedDate.day())
        self.insertCalendar()

    def setYear(self, date):
        self.selectedDate = QDate(date.year(), self.selectedDate.month(),
                self.selectedDate.day())
        self.insertCalendar()