def create_line_search(self, hostnames_list):
        """
        Add all hosts to QLineEdit and set QCompleter

        :param hostnames_list: list of host names
        :type hostnames_list: list
        """

        # Get QStringListModel
        model = self.completer.model()
        if not model:
            model = QStringListModel()

        model.setStringList(hostnames_list)

        # Configure QCompleter from model
        self.completer.setFilterMode(Qt.MatchContains)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setModel(model)
        self.completer.popup().setObjectName('popup')

        # Add completer to QLineEdit
        self.line_search.setCompleter(self.completer)
        self.line_search.setPlaceholderText(
            _('Type a host name to display its data'))
        self.line_search.setToolTip(_('Type a host name to display its data'))
Example #2
0
    def create_line_search(self):
        """
        Add all hosts to QLineEdit and set QCompleter

        """

        # Create list for QStringModel
        hosts_list = []
        params = {'where': json.dumps({'_is_template': False})}

        all_hosts = self.app_backend.get('host', params, ['name'])

        if all_hosts:
            for host in all_hosts['_items']:
                hosts_list.append(host['name'])

        model = QStringListModel()
        model.setStringList(hosts_list)

        # Create completer from model
        completer = QCompleter()
        completer.setFilterMode(Qt.MatchContains)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setModel(model)

        # Add completer to "line edit"
        self.line_search.setCompleter(completer)
        self.line_search.setPlaceholderText(
            'Type a host name to display its data')
        self.line_search.setToolTip('Type a host name to display its data')
    def create_line_search(self, hostnames_list):
        """
        Add all hosts to QLineEdit and set QCompleter

        :param hostnames_list: list of host names
        :type hostnames_list: list
        """

        # Get QStringListModel
        model = self.completer.model()
        if not model:
            model = QStringListModel()

        model.setStringList(hostnames_list)

        # Configure QCompleter from model
        self.completer.setFilterMode(Qt.MatchContains)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setModel(model)
        self.completer.popup().setObjectName('popup')

        # Add completer to QLineEdit
        self.line_search.setCompleter(self.completer)
        self.line_search.setPlaceholderText(_('Type a host name to display its data'))
        self.line_search.setToolTip(_('Type a host name to display its data'))
Example #4
0
    def __init__(self, dirLister, entryProvider: IEntryProvider,
                 newEntryText: str, itemNameNormalizer: IItemNameNormalizer):
        super().__init__()

        def initListView():
            self.listView = QListView()
            self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            self.listView.setModel(self.model)
            self.listView.setMinimumWidth(200)

            actionRemove = QAction("Remove", None)
            self.listView.addAction(actionRemove)

            self.listView.selectionModel().currentChanged.connect(
                lambda selectedItem, unselectedItem: self.onEntrySelected.emit(
                    self.itemNameNormalizer.normalizeName(
                        self.currentDir.filePath(selectedItem.data()))))

            def contextMenu(position):
                menu = QMenu()
                index = self.listView.indexAt(position)
                entry = self.model.data(index, Qt.DisplayRole)

                deleteAction = None
                renameAction = None

                addAction = menu.addAction("Add")

                if entry is not None:
                    deleteAction = menu.addAction("Delete")
                    renameAction = menu.addAction("Rename")

                refreshAction = menu.addAction("Refresh")

                chosenAction = menu.exec_(self.listView.mapToGlobal(position))

                if chosenAction is None:
                    return

                if chosenAction == deleteAction:
                    self.onRemoveRequested.emit(entry)
                elif chosenAction == renameAction:
                    self.renameEntry(index, entry)
                elif chosenAction == addAction:
                    self.onCreateNewEntry()
                elif chosenAction == refreshAction:
                    self.refreshListViewEntries()

            self.listView.customContextMenuRequested.connect(contextMenu)
            self.listView.setContextMenuPolicy(Qt.CustomContextMenu)

        self.currentDir: QDir = None
        self.model = QStringListModel()
        self.directoryLister = dirLister
        self.entryProvider = entryProvider
        self.newEntryText = newEntryText
        self.itemNameNormalizer = itemNameNormalizer
        self.sortingParser: IEntrySorting
        initListView()
    def __init__(self, current_family, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose font family'))
        self.setWindowIcon(QIcon(I('font.png')))
        from calibre.utils.fonts.scanner import font_scanner
        self.font_scanner = font_scanner

        self.m = QStringListModel(self)
        self.build_font_list()
        self.l = l = QGridLayout()
        self.setLayout(l)
        self.view = FontsView(self)
        self.view.setModel(self.m)
        self.view.setCurrentIndex(self.m.index(0))
        if current_family:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(current_family):
                    self.view.setCurrentIndex(self.m.index(i))
                    break
        self.view.doubleClicked.connect(
            self.accept, type=Qt.ConnectionType.QueuedConnection)
        self.view.changed.connect(self.current_changed,
                                  type=Qt.ConnectionType.QueuedConnection)
        self.faces = Typefaces(self)
        self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok
                                   | QDialogButtonBox.StandardButton.Cancel)
        self.bb.accepted.connect(self.accept)
        self.bb.rejected.connect(self.reject)
        self.add_fonts_button = afb = self.bb.addButton(
            _('Add &fonts'), self.bb.ActionRole)
        afb.setIcon(QIcon(I('plus.png')))
        afb.clicked.connect(self.add_fonts)
        self.ml = QLabel(_('Choose a font family from the list below:'))
        self.search = QLineEdit(self)
        self.search.setPlaceholderText(_('Search'))
        self.search.returnPressed.connect(self.find)
        self.nb = QToolButton(self)
        self.nb.setIcon(QIcon(I('arrow-down.png')))
        self.nb.setToolTip(_('Find next'))
        self.pb = QToolButton(self)
        self.pb.setIcon(QIcon(I('arrow-up.png')))
        self.pb.setToolTip(_('Find previous'))
        self.nb.clicked.connect(self.find_next)
        self.pb.clicked.connect(self.find_previous)

        l.addWidget(self.ml, 0, 0, 1, 4)
        l.addWidget(self.search, 1, 0, 1, 1)
        l.addWidget(self.nb, 1, 1, 1, 1)
        l.addWidget(self.pb, 1, 2, 1, 1)
        l.addWidget(self.view, 2, 0, 1, 3)
        l.addWidget(self.faces, 1, 3, 2, 1)
        l.addWidget(self.bb, 3, 0, 1, 4)
        l.setAlignment(self.faces, Qt.AlignmentFlag.AlignTop)

        self.resize(800, 600)
Example #6
0
class RichTextDelegate(QStyledItemDelegate):  # {{{

    def __init__(self, parent=None, max_width=160):
        QStyledItemDelegate.__init__(self, parent)
        self.max_width = max_width
        self.dummy_model = QStringListModel([' '], self)
        self.dummy_index = self.dummy_model.index(0)

    def to_doc(self, index, option=None):
        doc = QTextDocument()
        if option is not None and option.state & QStyle.State_Selected:
            p = option.palette
            group = (p.Active if option.state & QStyle.State_Active else
                    p.Inactive)
            c = p.color(group, p.HighlightedText)
            c = 'rgb(%d, %d, %d)'%c.getRgb()[:3]
            doc.setDefaultStyleSheet(' * { color: %s }'%c)
        doc.setHtml(index.data() or '')
        return doc

    def sizeHint(self, option, index):
        doc = self.to_doc(index, option=option)
        ans = doc.size().toSize()
        if ans.width() > self.max_width - 10:
            ans.setWidth(self.max_width)
        ans.setHeight(ans.height()+10)
        return ans

    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(self, painter, option, self.dummy_index)
        painter.save()
        painter.setClipRect(QRectF(option.rect))
        painter.translate(option.rect.topLeft())
        self.to_doc(index, option).drawContents(painter)
        painter.restore()
Example #7
0
class RichTextDelegate(QStyledItemDelegate):  # {{{
    def __init__(self, parent=None, max_width=160):
        QStyledItemDelegate.__init__(self, parent)
        self.max_width = max_width
        self.dummy_model = QStringListModel([' '], self)
        self.dummy_index = self.dummy_model.index(0)

    def to_doc(self, index, option=None):
        doc = QTextDocument()
        if option is not None and option.state & QStyle.State_Selected:
            p = option.palette
            group = (p.Active if option.state
                     & QStyle.State_Active else p.Inactive)
            c = p.color(group, p.HighlightedText)
            c = 'rgb(%d, %d, %d)' % c.getRgb()[:3]
            doc.setDefaultStyleSheet(' * { color: %s }' % c)
        doc.setHtml(index.data() or '')
        return doc

    def sizeHint(self, option, index):
        doc = self.to_doc(index, option=option)
        ans = doc.size().toSize()
        if ans.width() > self.max_width - 10:
            ans.setWidth(self.max_width)
        ans.setHeight(ans.height() + 10)
        return ans

    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(self, painter, option, self.dummy_index)
        painter.save()
        painter.setClipRect(QRectF(option.rect))
        painter.translate(option.rect.topLeft())
        self.to_doc(index, option).drawContents(painter)
        painter.restore()
Example #8
0
    def _initUI(self):
        """
        Load the ui file for the central widget.
        """
        uic.loadUi(self._ui_path, self)
        self.typeList.setModel(QStringListModel(types.SERVER_TYPES))

        # Trigger state updates
        self.nameEdit.textChanged.connect(self._updateConfigFromFields)
        self.pathEdit.textChanged.connect(self._updateConfigFromFields)
        self.addressEdit.textChanged.connect(self._updateConfigFromFields)
        self.typeList.currentTextChanged.connect(self._updateConfigFromFields)
        self.portEdit.textChanged.connect(self._updateConfigFromFields)
        self.usernameEdit.textChanged.connect(self._updateConfigFromFields)
        self.sshKeyEdit.textChanged.connect(self._updateConfigFromFields)
        self.deviceList.itemChanged.connect(self._updateConfigFromFields)
        self.autostartCheckBox.stateChanged.connect(
            self._updateConfigFromFields)

        # UI updates
        self.addressEdit.textChanged.connect(self._setServerTypeFromAddress)
        self.typeList.currentTextChanged.connect(
            self._changeRemoteFieldsVisibility)
        self.getDevicesBtn.clicked.connect(self._setDevices)
        self.deviceList.itemClicked.connect(self._deviceListSetCheckboxOnClick)
Example #9
0
    def update(self, text_items, completion_prefix):
        items = list(self.all_items.difference(text_items))
        model = QStringListModel(items, self)
        self.setModel(model)

        self.setCompletionPrefix(completion_prefix)
        if completion_prefix.strip():
            self.complete()
Example #10
0
 def createEditor(self, parent, option, index):
     editor = BulkValueSelectorWidget(parent)
     editor.setFixedHeight(int(self.parent().height() * 0.8))
     editor.setFixedWidth(200)
     editor.values = QStringListModel(self.parent().model().data(index, EditorAuxDataRole), self)
     editor.selectedValues = self.parent().model().data(index, DataRole)
     popup = Popup(parent, editor)
     editor.dataCommitted.connect(self.closePopup(popup))
     return popup
Example #11
0
class Delegate(QStyledItemDelegate):

    def __init__(self, parent=None):
        QStyledItemDelegate.__init__(self, parent)
        self._m = QStringListModel(['sdfgkjsg sopgjs gsgs slgjslg sdklgsgl', ''])

    def sizeHint(self, option, index):
        ans = QStyledItemDelegate.sizeHint(self, option, self._m.index(0))
        index.data(Qt.UserRole).adjust_size_hint(option, ans)
        return ans

    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(self, painter, option, self._m.index(1))
        painter.save()
        parent = self.parent() or QApplication.instance()
        style = parent.style()
        try:
            index.data(Qt.UserRole).draw_item(painter, style, option)
        finally:
            painter.restore()
Example #12
0
File: ask.py Project: alok/vise
class Delegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        QStyledItemDelegate.__init__(self, parent)
        self._m = QStringListModel(
            ['sdfgkjsg sopgjs gsgs slgjslg sdklgsgl', ''])

    def sizeHint(self, option, index):
        ans = QStyledItemDelegate.sizeHint(self, option, self._m.index(0))
        index.data(Qt.UserRole).adjust_size_hint(option, ans)
        return ans

    def paint(self, painter, option, index):
        QStyledItemDelegate.paint(self, painter, option, self._m.index(1))
        painter.save()
        parent = self.parent() or QApplication.instance()
        style = parent.style()
        try:
            index.data(Qt.UserRole).draw_item(painter, style, option)
        finally:
            painter.restore()
Example #13
0
    def __init__(self, current_family, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose font family'))
        self.setWindowIcon(QIcon(I('font.png')))
        from calibre.utils.fonts.scanner import font_scanner
        self.font_scanner = font_scanner

        self.m = QStringListModel(self)
        self.build_font_list()
        self.l = l = QGridLayout()
        self.setLayout(l)
        self.view = FontsView(self)
        self.view.setModel(self.m)
        self.view.setCurrentIndex(self.m.index(0))
        if current_family:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(current_family):
                    self.view.setCurrentIndex(self.m.index(i))
                    break
        self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection)
        self.view.changed.connect(self.current_changed,
                type=Qt.QueuedConnection)
        self.faces = Typefaces(self)
        self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        self.bb.accepted.connect(self.accept)
        self.bb.rejected.connect(self.reject)
        self.add_fonts_button = afb = self.bb.addButton(_('Add &fonts'),
                self.bb.ActionRole)
        afb.setIcon(QIcon(I('plus.png')))
        afb.clicked.connect(self.add_fonts)
        self.ml = QLabel(_('Choose a font family from the list below:'))
        self.search = QLineEdit(self)
        self.search.setPlaceholderText(_('Search'))
        self.search.returnPressed.connect(self.find)
        self.nb = QToolButton(self)
        self.nb.setIcon(QIcon(I('arrow-down.png')))
        self.nb.setToolTip(_('Find next'))
        self.pb = QToolButton(self)
        self.pb.setIcon(QIcon(I('arrow-up.png')))
        self.pb.setToolTip(_('Find previous'))
        self.nb.clicked.connect(self.find_next)
        self.pb.clicked.connect(self.find_previous)

        l.addWidget(self.ml, 0, 0, 1, 4)
        l.addWidget(self.search, 1, 0, 1, 1)
        l.addWidget(self.nb, 1, 1, 1, 1)
        l.addWidget(self.pb, 1, 2, 1, 1)
        l.addWidget(self.view, 2, 0, 1, 3)
        l.addWidget(self.faces, 1, 3, 2, 1)
        l.addWidget(self.bb, 3, 0, 1, 4)
        l.setAlignment(self.faces, Qt.AlignTop)

        self.resize(800, 600)
Example #14
0
    def __init__(self, gui, icon, do_user_config):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config

        self.db = gui.current_db.new_api

        # The model for the book list
        self.model = OpdsBooksModel(None, self.dummy_books(), self.db)
        self.searchproxymodel = QSortFilterProxyModel(self)
        self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.searchproxymodel.setFilterKeyColumn(-1)
        self.searchproxymodel.setSourceModel(self.model)

        self.layout = QGridLayout()
        self.setLayout(self.layout)

        self.setWindowTitle("OPDS Client")
        self.setWindowIcon(icon)

        labelColumnWidths = []

        self.opdsUrlLabel = QLabel("OPDS URL: ")
        self.layout.addWidget(self.opdsUrlLabel, 0, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width())

        config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference()
        self.opdsUrlEditor = QComboBox(self)
        self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated)
        self.opdsUrlEditor.addItems(prefs["opds_url"])
        self.opdsUrlEditor.setEditable(True)
        self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop)
        self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3)
        self.opdsUrlLabel.setBuddy(self.opdsUrlEditor)

        buttonColumnNumber = 7
        buttonColumnWidths = []
        self.about_button = QPushButton("About", self)
        self.about_button.setAutoDefault(False)
        self.about_button.clicked.connect(self.about)
        self.layout.addWidget(self.about_button, 0, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width()
        )

        # Initially download the catalogs found in the root catalog of the URL
        # selected at startup.  Fail quietly on failing to open the URL
        catalogsTuple = self.model.downloadOpdsRootCatalog(
            self.gui, self.opdsUrlEditor.currentText(), False
        )
        print(catalogsTuple)
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1]  # A dictionary of title->feedURL

        self.opdsCatalogSelectorLabel = QLabel("OPDS Catalog:")
        self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width())

        self.opdsCatalogSelector = QComboBox(self)
        self.opdsCatalogSelector.setEditable(False)
        self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel)
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)
        self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3)

        self.download_opds_button = QPushButton("Download OPDS", self)
        self.download_opds_button.setAutoDefault(False)
        self.download_opds_button.clicked.connect(self.download_opds)
        self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width()
        )

        # Search GUI
        self.searchEditor = QLineEdit(self)
        self.searchEditor.returnPressed.connect(self.searchBookList)
        self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2)

        self.searchButton = QPushButton("Search", self)
        self.searchButton.setAutoDefault(False)
        self.searchButton.clicked.connect(self.searchBookList)
        self.layout.addWidget(self.searchButton, 2, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width()
        )

        # The main book list
        self.library_view = QTableView(self)
        self.library_view.setAlternatingRowColors(True)
        self.library_view.setModel(self.searchproxymodel)
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.library_view.resizeColumnsToContents()
        self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1)

        self.hideNewsCheckbox = QCheckBox("Hide Newspapers", self)
        self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers)
        self.hideNewsCheckbox.setChecked(prefs["hideNewspapers"])
        self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3)

        self.hideBooksAlreadyInLibraryCheckbox = QCheckBox("Hide books already in library", self)
        self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary)
        self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs["hideBooksAlreadyInLibrary"])
        self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3)

        # Let the checkbox initial state control the filtering
        self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked())
        self.model.setFilterBooksThatAreAlreadyInLibrary(
            self.hideBooksAlreadyInLibraryCheckbox.isChecked()
        )

        self.downloadButton = QPushButton("Download selected books", self)
        self.downloadButton.setAutoDefault(False)
        self.downloadButton.clicked.connect(self.downloadSelectedBooks)
        self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width()
        )

        self.fixTimestampButton = QPushButton("Fix timestamps of selection", self)
        self.fixTimestampButton.setAutoDefault(False)
        self.fixTimestampButton.clicked.connect(self.fixBookTimestamps)
        self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width()
        )

        # Make all columns of the grid layout the same width as the button column
        buttonColumnWidth = max(buttonColumnWidths)
        for columnNumber in range(0, buttonColumnNumber):
            self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth)

        # Make sure the first column isn't wider than the labels it holds
        labelColumnWidth = max(labelColumnWidths)
        self.layout.setColumnMinimumWidth(0, labelColumnWidth)

        self.resize(self.sizeHint())
Example #15
0
class OpdsDialog(QDialog):
    def __init__(self, gui, icon, do_user_config):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config

        self.db = gui.current_db.new_api

        # The model for the book list
        self.model = OpdsBooksModel(None, self.dummy_books(), self.db)
        self.searchproxymodel = QSortFilterProxyModel(self)
        self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.searchproxymodel.setFilterKeyColumn(-1)
        self.searchproxymodel.setSourceModel(self.model)

        self.layout = QGridLayout()
        self.setLayout(self.layout)

        self.setWindowTitle("OPDS Client")
        self.setWindowIcon(icon)

        labelColumnWidths = []

        self.opdsUrlLabel = QLabel("OPDS URL: ")
        self.layout.addWidget(self.opdsUrlLabel, 0, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width())

        config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference()
        self.opdsUrlEditor = QComboBox(self)
        self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated)
        self.opdsUrlEditor.addItems(prefs["opds_url"])
        self.opdsUrlEditor.setEditable(True)
        self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop)
        self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3)
        self.opdsUrlLabel.setBuddy(self.opdsUrlEditor)

        buttonColumnNumber = 7
        buttonColumnWidths = []
        self.about_button = QPushButton("About", self)
        self.about_button.setAutoDefault(False)
        self.about_button.clicked.connect(self.about)
        self.layout.addWidget(self.about_button, 0, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width()
        )

        # Initially download the catalogs found in the root catalog of the URL
        # selected at startup.  Fail quietly on failing to open the URL
        catalogsTuple = self.model.downloadOpdsRootCatalog(
            self.gui, self.opdsUrlEditor.currentText(), False
        )
        print(catalogsTuple)
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1]  # A dictionary of title->feedURL

        self.opdsCatalogSelectorLabel = QLabel("OPDS Catalog:")
        self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width())

        self.opdsCatalogSelector = QComboBox(self)
        self.opdsCatalogSelector.setEditable(False)
        self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel)
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)
        self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3)

        self.download_opds_button = QPushButton("Download OPDS", self)
        self.download_opds_button.setAutoDefault(False)
        self.download_opds_button.clicked.connect(self.download_opds)
        self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width()
        )

        # Search GUI
        self.searchEditor = QLineEdit(self)
        self.searchEditor.returnPressed.connect(self.searchBookList)
        self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2)

        self.searchButton = QPushButton("Search", self)
        self.searchButton.setAutoDefault(False)
        self.searchButton.clicked.connect(self.searchBookList)
        self.layout.addWidget(self.searchButton, 2, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width()
        )

        # The main book list
        self.library_view = QTableView(self)
        self.library_view.setAlternatingRowColors(True)
        self.library_view.setModel(self.searchproxymodel)
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.library_view.resizeColumnsToContents()
        self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1)

        self.hideNewsCheckbox = QCheckBox("Hide Newspapers", self)
        self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers)
        self.hideNewsCheckbox.setChecked(prefs["hideNewspapers"])
        self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3)

        self.hideBooksAlreadyInLibraryCheckbox = QCheckBox("Hide books already in library", self)
        self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary)
        self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs["hideBooksAlreadyInLibrary"])
        self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3)

        # Let the checkbox initial state control the filtering
        self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked())
        self.model.setFilterBooksThatAreAlreadyInLibrary(
            self.hideBooksAlreadyInLibraryCheckbox.isChecked()
        )

        self.downloadButton = QPushButton("Download selected books", self)
        self.downloadButton.setAutoDefault(False)
        self.downloadButton.clicked.connect(self.downloadSelectedBooks)
        self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width()
        )

        self.fixTimestampButton = QPushButton("Fix timestamps of selection", self)
        self.fixTimestampButton.setAutoDefault(False)
        self.fixTimestampButton.clicked.connect(self.fixBookTimestamps)
        self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber)
        buttonColumnWidths.append(
            self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width()
        )

        # Make all columns of the grid layout the same width as the button column
        buttonColumnWidth = max(buttonColumnWidths)
        for columnNumber in range(0, buttonColumnNumber):
            self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth)

        # Make sure the first column isn't wider than the labels it holds
        labelColumnWidth = max(labelColumnWidths)
        self.layout.setColumnMinimumWidth(0, labelColumnWidth)

        self.resize(self.sizeHint())

    def opdsUrlEditorActivated(self, text):
        prefs["opds_url"] = config.saveOpdsUrlCombobox(self.opdsUrlEditor)
        catalogsTuple = self.model.downloadOpdsRootCatalog(
            self.gui, self.opdsUrlEditor.currentText(), True
        )
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1]  # A dictionary of title->feedURL
        self.opdsCatalogSelectorModel.setStringList(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)

    def setHideNewspapers(self, checked):
        prefs["hideNewspapers"] = checked
        self.model.setFilterBooksThatAreNewspapers(checked)
        self.resizeAllLibraryViewLinesToHeaderHeight()

    def setHideBooksAlreadyInLibrary(self, checked):
        prefs["hideBooksAlreadyInLibrary"] = checked
        self.model.setFilterBooksThatAreAlreadyInLibrary(checked)
        self.resizeAllLibraryViewLinesToHeaderHeight()

    def searchBookList(self):
        searchString = self.searchEditor.text()
        print("starting book list search for: %s" % searchString)
        self.searchproxymodel.setFilterFixedString(searchString)

    def about(self):
        text = get_resources("about.txt")
        QMessageBox.about(self, "About the OPDS Client plugin", text.decode("utf-8"))

    def download_opds(self):
        opdsCatalogUrl = self.currentOpdsCatalogs.get(self.opdsCatalogSelector.currentText(), None)
        if opdsCatalogUrl is None:
            # Just give up quietly
            return
        self.model.downloadOpdsCatalog(self.gui, opdsCatalogUrl)
        if self.model.isCalibreOpdsServer():
            self.model.downloadMetadataUsingCalibreRestApi(self.opdsUrlEditor.currentText())
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.resize(self.sizeHint())

    def config(self):
        self.do_user_config(parent=self)

    def downloadSelectedBooks(self):
        selectionmodel = self.library_view.selectionModel()
        if selectionmodel.hasSelection():
            rows = selectionmodel.selectedRows()
            for row in reversed(rows):
                book = row.data(Qt.UserRole)
                self.downloadBook(book)

    def downloadBook(self, book):
        if len(book.links) > 0:
            self.gui.download_ebook(book.links[0])

    def fixBookTimestamps(self):
        selectionmodel = self.library_view.selectionModel()
        if selectionmodel.hasSelection():
            rows = selectionmodel.selectedRows()
            for row in reversed(rows):
                book = row.data(Qt.UserRole)
                self.fixBookTimestamp(book)

    def fixBookTimestamp(self, book):
        bookTimestamp = book.timestamp
        identicalBookIds = self.findIdenticalBooksForBooksWithMultipleAuthors(book)
        bookIdToValMap = {}
        for identicalBookId in identicalBookIds:
            bookIdToValMap[identicalBookId] = bookTimestamp
        if len(bookIdToValMap) < 1:
            print("Failed to set timestamp of book: %s" % book)
        self.db.set_field("timestamp", bookIdToValMap)

    def findIdenticalBooksForBooksWithMultipleAuthors(self, book):
        authorsList = book.authors
        if len(authorsList) < 2:
            return self.db.find_identical_books(book)
        # Try matching the authors one by one
        identicalBookIds = set()
        for author in authorsList:
            singleAuthorBook = Metadata(book.title, [author])
            singleAuthorIdenticalBookIds = self.db.find_identical_books(singleAuthorBook)
            identicalBookIds = identicalBookIds.union(singleAuthorIdenticalBookIds)
        return identicalBookIds

    def dummy_books(self):
        dummy_author = " " * 40
        dummy_title = " " * 60
        books_list = []
        for line in range(1, 10):
            book = DynamicBook()
            book.author = dummy_author
            book.title = dummy_title
            book.updated = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S+00:00")
            book.id = ""
            books_list.append(book)
        return books_list

    def resizeAllLibraryViewLinesToHeaderHeight(self):
        rowHeight = self.library_view.horizontalHeader().height()
        for rowNumber in range(0, self.library_view.model().rowCount()):
            self.library_view.setRowHeight(rowNumber, rowHeight)
Example #16
0
 def __init__(self, parent=None, max_width=160):
     QStyledItemDelegate.__init__(self, parent)
     self.max_width = max_width
     self.dummy_model = QStringListModel([' '], self)
     self.dummy_index = self.dummy_model.index(0)
Example #17
0
class LocationBar(LineEdit):

    # ProgressStyle
    _ProgressFilled = 0
    _ProgressBottom = 1
    _ProgressTop = 2

    class LoadAction:
        # enum Type
        Invalid = 0
        Search = 1
        Bookmark = 2
        Url = 3

        def __init__(self):
            self.type = self.Invalid
            self.searchEngine = SearchEngine()
            self.bookmark = None  # BookmarkItem
            self.loadRequest = LoadRequest()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._completer = None  # LocationCompleter
        self._domainCompleterModel = None  # QStringListModel

        self._bookmarkIcon = None  # BookmarksIcon
        self._goIcon = None  # GoIcon
        self._siteIcon = None  # SiteIcon
        self._autofillIcon = None  # AutoFillIcon

        self._window = None  # BrowserWindow
        self._webView = None  # TabbedWebView

        self._holdingAlt = False
        self._oldTextLength = 0
        self._currentTextLength = 0

        self._loadProgress = 0
        self._progressVisible = True
        self._progressStyle = 0  # ProgressStyle
        self._progressColor = QColor()
        self._progressTimer = None  # QTimer

        self.setObjectName('locationbar')
        self.setDragEnabled(True)

        # Disable KDE QLineEdit transitions, it breaks with setText() && home()
        self._bookmarkIcon = BookmarksIcon(self)
        self._goIcon = GoIcon(self)
        self._siteIcon = SiteIcon(self)
        self._autofillIcon = AutoFillIcon(self)
        down = DownIcon(self)

        self.addWidget(self._siteIcon, LineEdit.LeftSide)
        self.addWidget(self._autofillIcon, LineEdit.RightSide)
        self.addWidget(self._bookmarkIcon, LineEdit.RightSide)
        self.addWidget(self._goIcon, LineEdit.RightSide)
        self.addWidget(down, LineEdit.RightSide)

        self._completer = LocationCompleter(self)
        self._completer.setLocationBar(self)
        self._completer.showCompletion.connect(self._showCompletion)
        self._completer.showDomainCompletion.connect(
            self._showDomainCompletion)
        self._completer.clearCompletion.connect(self._clearCompletion)
        self._completer.loadRequested.connect(self.loadRequest)
        self._completer.popupClosed.connect(self._updateSiteIcon)

        self._domainCompleterModel = QStringListModel(self)
        domainCompleter = QCompleter(self)
        domainCompleter.setCompletionMode(QCompleter.InlineCompletion)
        domainCompleter.setModel(self._domainCompleterModel)
        self.setCompleter(domainCompleter)

        self._progressTimer = QTimer(self)
        self._progressTimer.setInterval(700)
        self._progressTimer.setSingleShot(True)
        self._progressTimer.timeout.connect(self._hideProgress)

        self.editAction(self.PasteAndGo).setText(_('Paste And &Go'))
        self.editAction(self.PasteAndGo).setIcon(QIcon.fromTheme('edit-paste'))
        self.editAction(self.PasteAndGo).triggered.connect(self._pasteAndGo)

        self.textEdited.connect(self._textEdited)
        self._goIcon.clicked.connect(self._requestLoadUrl)
        down.clicked.connect(self._completer.showMostVisited)
        # TODO:
        #gVar.app.searchEnginesManager().activeEngineChanged.connect(self._updatePlaceHolderText)
        #gVar.app.searchEnginesManager().defaultEngineChanged.connect(self._updatePlaceHolderText)

        self._loadSettings()

        self._updateSiteIcon()

        # Hide icons by default
        self._goIcon.setVisible(gVar.appSettings.alwaysShowGoIcon)
        self._autofillIcon.hide()

        QTimer.singleShot(0, self._updatePlaceHolderText)

    def browserWindow(self):
        '''
        @note: BrowserWindow can be null!
        @return: BrowserWindow
        '''
        return self._window

    def setBrowserWindow(self, window):
        self._window = window
        self._completer.setMainWindow(self._window)
        self._siteIcon.setBrowserWindow(self._window)

    def webView(self):
        '''
        @return TabbedWebView
        '''
        return self._webView

    def setWebView(self, view):
        '''
        @param: view TabbedWebView -> WebView -> QWebEngineView
        '''
        self._webView = view

        self._bookmarkIcon.setWebView(self._webView)
        self._siteIcon.setWebView(self._webView)
        self._autofillIcon.setWebView(self._webView)

        self._webView.loadStarted.connect(self._loadStarted)
        self._webView.loadProgress.connect(self.__loadProgress)
        self._webView.loadFinished.connect(self._loadFinished)
        self._webView.urlChanged.connect(self.showUrl)
        self._webView.privacyChanged.connect(self._setPrivacyState)

    @classmethod
    def convertUrlToText(cls, url):
        '''
        @note: It was most probably entered by user, so don't urlencode it Also don't urlencode JavaScript code
        @param: url QUrl
        @return: QString
        '''
        if not url.scheme() or url.scheme() == 'javascript':
            return QUrl.fromPercentEncoding(url.toEncoded())

        stringUrl = gVar.appTools.urlEncodeQueryString(url)

        if stringUrl == 'app:speeddial' or stringUrl == 'about:blank':
            stringUrl = ''

        return stringUrl

    @classmethod
    def searchEngine(cls):
        '''
        @return: SearchEngine
        '''
        if not gVar.appSettings.searchFromAddressBar:
            return SearchEngine()
        elif gVar.appSettings.searchWithDefaultEngine:
            return gVar.app.searchEnginesManager().defaultEngine()
        else:
            return gVar.app.searchEnginesManager().activeEngine()

    @classmethod
    def loadAction(cls, text):
        '''
        @return: LoadAction
        '''
        action = cls.LoadAction()

        t = text.strip()
        if not t:
            return action

        # Check for Search Engine shortcut
        firstSpacePos = t.find(' ')
        if gVar.appSettings.searchFromAddressBar and firstSpacePos != -1:
            shortcut = t[:firstSpacePos]
            searchedString = t[firstSpacePos:].strip()

            en = gVar.app.searchEnginesManager().engineForShortcut(shortcut)
            if en.isValid():
                action.type = cls.LoadAction.Search
                action.searchEngine = en
                url = gVar.app.searchEnginesManager().searchResult(
                    en, searchedString)
                action.loadRequest = LoadRequest(url)
                return action

        # Check for Bookmark keyword
        items = gVar.app.bookmarks().searchKeyword(t)
        if items:
            item = items[0]
            action.type = cls.LoadAction.Bookmark
            action.bookmark = item
            action.loadRequest.setUrl(item.url())
            return action

        if not gVar.appSettings.searchFromAddressBar:
            guessedUrl = QUrl.fromUserInput(t)
            if guessedUrl.isValid():
                action.type = cls.LoadAction.Url
                action.loadRequest = LoadRequest(guessedUrl)
            return action

        # Check for one word search
        if t != 'localhost' \
                and gVar.appTools.containsSpace(t) \
                and '.' not in t \
                and ':' not in t \
                and '/' not in t:
            action.type = cls.LoadAction.Search
            action.searchEngine = cls.searchEngine()
            url = gVar.app.searchEnginesManager().searchResult(
                cls.searchEngine(), t)
            action.loadRequest = LoadRequest(url)
            return action

        # Otherwise load as url
        guessedUrl = QUrl.fromUserInput(t)
        if guessedUrl.isValid():
            # Always allow javascript: to be loaded
            forceLoad = guessedUrl.scheme() == 'javascript'
            # Only allow spaces in query
            urlRaw = guessedUrl.toString(QUrl.RemoveQuery)
            if forceLoad or not gVar.appTools.containsSpace(t) or \
                    not gVar.appTools.contiansSpace(urlRaw):
                # Only allow supported schemes
                if forceLoad or guessedUrl.scheme(
                ) in WebPage.supportedSchemes():
                    action.type = cls.LoadAction.Url
                    action.loadRequest = LoadRequest(guessedUrl)
                    return action

        # Search when creating url failed
        action.type = cls.LoadAction.Search
        action.searchEngine = cls.searchEngine()
        url = gVar.app.searchEnginesManager().searchResult(
            cls.searchEngine(), t)
        action.loadRequest = LoadRequest(url)
        return action

    # public Q_SLOTS
    def setText(self, text):
        # TODO: ?
        self._oldTextLength = len(text)
        self._currentTextLength = self._oldTextLength

        super().setText(text)

        self._refreshTextFormat()

    def showUrl(self, url):
        if self.hasFocus() or url.isEmpty():
            return

        stringUrl = self.convertUrlToText(url)

        if self.text() == stringUrl:
            self.home(False)
            self._refreshTextFormat()
            return

        # Set converted url as text
        self.setText(stringUrl)

        # Move cursor to the start
        self.home(False)

        self._bookmarkIcon.checkBookmark(url)

    def loadRequest(self, request):
        '''
        @param: request LoadRequest
        '''
        if not self._webView.webTab().isRestored():
            return

        urlString = self.convertUrlToText(request.url())

        self._completer.closePopup()
        self._webView.setFocus()

        if urlString != self.text():
            self.setText(urlString)

        self._webView.userLoadAction(request)

    # private Q_SLOTS
    def _textEdited(self, text):
        self._oldTextLength = self._currentTextLength
        self._currentTextLength = len(text)

        if text:
            self._completer.complete(text)
            icon = QIcon.fromTheme('edit-find',
                                   QIcon(':/icons/menu/search-icon.svg'))
            self._siteIcon.setIcon(icon)
        else:
            self._completer.closePopup()

        self._setGoIconVisible(True)

    def _requestLoadUrl(self):
        req = self.loadAction(self.text()).loadRequest
        self.loadRequest(req)
        self._updateSiteIcon()

    def _pasteAndGo(self):
        self.clear()
        self.paste()
        self._requestLoadUrl()

    def _updateSiteIcon(self):
        if self._completer.isVisible():
            self._siteIcon.setIcon(
                QIcon.fromTheme('edit-find',
                                QIcon(':/icons/menu/search-icon.svg')))
        else:
            icon = IconProvider.emptyWebIcon()
            secured = self.property('secured')
            if secured:
                icon = QIcon.fromTheme('document-encrypted', icon)
            self._siteIcon.setIcon(icon.pixmap(16))

    def _updatePlaceHolderText(self):
        if gVar.appSettings.searchFromAddressBar:
            self.setPlaceholderText(
                _('Enter address or search with %s') %
                self.searchEngine().name)
        else:
            self.setPlaceholderText(_('Enter address'))

    def _setPrivacyState(self, state):
        '''
        @param: state bool
        '''
        self._siteIcon.setProperty('secured', state)
        self._siteIcon.style().unpolish(self._siteIcon)
        self._siteIcon.style().polish(self._siteIcon)

        self.setProperty('secured', state)
        self.style().unpolish(self)
        self.style().polish(self)

        self._updateSiteIcon()

    def _setGoIconVisible(self, state):
        '''
        @param: state bool
        '''
        if state:
            self._bookmarkIcon.hide()
            self._goIcon.show()
        else:
            self._bookmarkIcon.show()
            if not gVar.appSettings.alwaysShowGoIcon:
                self._goIcon.hide()

        self.updateTextMargins()

    def _showCompletion(self, completion, completeDomain):
        '''
        @param: completion QString
        @param: completeDomain bool
        '''
        super().setText(completion)

        # Move cursor to the end
        self.end(False)

        if completeDomain:
            self.completer().complete()

        self._updateSiteIcon()

    def _showDomainCompletion(self, completion):
        '''
        @param: completion QString
        '''
        self._domainCompleterModel.setStringList([completion])

        # We need to manually force the completion because model is updated
        # asynchronously, But only force completion when theuser actually added
        # new text
        if completion and self._oldTextLength < self._currentTextLength:
            self.completer().complete()

    def _clearCompletion(self):
        self._webView.setFocus()
        self.showUrl(self._webView.url())

    def _loadStarted(self):
        self._progressVisible = True
        self._progressTimer.start()
        self._autofillIcon.hide()

    def __loadProgress(self, progress):
        '''
        @param: progress int
        '''
        if gVar.appSettings.showLoadingProgress:
            self._loadProgress = progress
            self.update()

    def _loadFinished(self):
        if gVar.appSettings.showLoadingProgress:
            self._progressTimer.start()

        page = self._webView.page()
        if isinstance(page, WebPage) and page.autoFillUsernames():
            self._autofillIcon.setUsernames(page.autoFillUsernames())
            self._autofillIcon.show()

    def _hideProgress(self):
        if gVar.appSettings.showLoadingProgress:
            self._progressVisible = False
            self.update()

    def _loadSettings(self):
        settings = Settings()
        settings.beginGroup('AddressBar')
        self._progressStyle = settings.value('ProgressStyle', 0)
        customColor = settings.value('UseCustomProgressColor', False)
        if customColor:
            self._progressColor = settings.value(
                'CustomProgressColor',
                self.palette().color(QPalette.Highlight))
        else:
            self._progressColor = QColor()
        settings.endGroup()

    # private:
    # override
    def contextMenuEvent(self, event):
        '''
        @param: event QContextMenuEvent
        '''
        menu = self._createContextMenu()
        menu.setAttribute(Qt.WA_DeleteOnClose)

        # Prevent choosing first option with double rightclick
        pos = event.globalPos()
        pos.setY(pos.y() + 1)
        menu.popup(pos)

    # override
    def showEvent(self, event):
        '''
        @param: event QShowEvent
        '''
        super().showEvent(event)

        self._refreshTextFormat()

    # override
    def focusInEvent(self, event):
        '''
        @param: event QFocusEvent
        '''
        if self._webView:
            stringUrl = self.convertUrlToText(self._webView.url())

            # Text has been edited, let's show go button
            if stringUrl != self.text():
                self._setGoIconVisible(True)

        self.clearTextFormat()
        super().focusInEvent(event)

        if self._window and Settings().value(
                'Browser-View-Settings/instantBookmarksToolbar', type=bool):
            self._window.bookmarksToolbar().show()

    # override
    def focusOutEvent(self, event):
        '''
        @param: event QFocusEvent
        '''
        # Context menu or completer popup were opened
        # Let's block focusOutEvent to trick QLineEdit and point cursor properly
        if event.reason() == Qt.PopupFocusReason:  # TODO: ?
            return

        super().focusOutEvent(event)

        self._setGoIconVisible(False)

        if not self.text().strip():
            self.clear()

        self._refreshTextFormat()

        if self._window and Settings().value(
                'Browser-View-Settings/instantBookmarksToolbar', type=bool):
            self._window.bookmarksToolbar().hide()

    # override
    def keyPressEvent(self, event):  # noqa C901
        '''
        @param: event QKeyEvent
        '''
        evtKey = event.key()
        evtModifiers = event.modifiers()
        if evtKey == Qt.Key_V:
            if event.modifiers() == (Qt.ControlModifier | Qt.ShiftModifier):
                self._pasteAndGo()
                event.accept()
                return
        elif evtKey == Qt.Key_Down:
            self._completer.complete(self.text())
        elif evtKey == Qt.Key_Left:
            self._completer.closePopup()
        elif evtKey == Qt.Key_Escape:
            self._webView.setFocus()
            self.showUrl(self._webView.url())
            event.accept()
        elif evtKey == Qt.Key_Alt:
            self._holdingAlt = True
        elif evtKey in (Qt.Key_Return, Qt.Key_Enter):
            if evtModifiers == Qt.ControlModifier:
                if not self.text().endswith('.com'):
                    self.setText(self.text() + '.com')
                self.requestLoadUrl()
            elif evtModifiers == Qt.AltModifier:
                self._completer.closePopup()
                if self._window:
                    req = self.loadAction(self.text()).loadRequest
                    self._window.tabWidget().addViewByReq(req)
            else:
                self._requestLoadUrl()

            self._holdingAlt = False

        elif evtKey in (
                Qt.Key_0,
                Qt.Key_1,
                Qt.Key_2,
                Qt.Key_3,
                Qt.Key_4,
                Qt.Key_5,
                Qt.Key_6,
                Qt.Key_7,
                Qt.Key_8,
                Qt.Key_9,
        ):
            if evtModifiers & Qt.AltModifier or evtModifiers & Qt.ControlModifier:
                event.ignore()
                self._holdingAlt = False
                return
        else:
            self._holdingAlt = False

        super().keyPressEvent(event)

    # override
    def dropEvent(self, event):
        '''
        @param: event QDropEvent
        '''
        if event.mimeData().hasUrls():
            dropUrl = event.mimeData().urls()[0]
            if WebView.isUrlValid(dropUrl):
                self.setText(dropUrl.toString())
                self.loadRequest(LoadRequest(dropUrl))

                event = QFocusEvent(QFocusEvent.FocusOut)
                super().focusOutEvent(event)
                return
        elif event.mimeData().hasText():
            dropText = event.mimeData().text().strip()
            dropUrl = QUrl(dropText)
            if WebView.isUrlValid(dropUrl):
                self.setText(dropUrl.toString())
                self.loadRequest(LoadRequest(dropUrl))

                event = QFocusEvent(QFocusEvent.FocusOut)
                super().focusOutEvent(event)
                return
            else:
                self.setText(dropText)
                self.setFocus()
                return

        super().dropEvent(event)

    # override
    def paintEvent(self, event):
        '''
        @param: event QPaintEvent
        '''
        super().paintEvent(event)

        # Show loading progress
        if gVar.appSettings.showLoadingProgress and self._progressVisible:
            option = QStyleOptionFrame()
            self.initStyleOption(option)

            lm, tm, rm, bm = self.getTextMargins()

            contentsRect = self.style().subElementRect(
                QStyle.SE_LineEditContents, option, self)
            contentsRect.adjust(lm, tm, -rm, -bm)

            bg = QColor(self._progressColor)
            if not bg.isValid() or bg.alpha() == 0:
                pal = self.palette()
                bg = Colors.mid(pal.color(QPalette.Base),
                                pal.color(QPalette.Text),
                                self._progressStyle > 0 and 4 or 8, 1)

            p = QPainter(self)
            p.setBrush(QBrush(bg))

            # We are painting over text, make sure the text stays visible
            p.setOpacity(0.5)

            outlinePen = QPen(bg.darker(110), 0.8)
            p.setPen(outlinePen)

            if self._progressStyle == self._ProgressFilled:
                bar = contentsRect.adjusted(0, 1, 0, -1)
                bar.setWidth(int(bar.width() * self._loadProgress / 100))
                roundness = bar.height() / 4.0
                p.drawRoundedRect(bar, roundness, roundness)
            elif self._progressStyle == self._ProgressBottom:
                outlinePen.setWidthF(0.3)
                outlinePen.setColor(outlinePen.color().darker(130))
                p.setPen(outlinePen)
                bar = QRect(contentsRect.x(),
                            contentsRect.bottom() - 3,
                            contentsRect.width() * self._loadProgress / 100.0,
                            3)
                p.drawRoundedRect(bar, 1, 1)
            elif self._progressStyle == self._ProgressTop:
                outlinePen.setWidthF(0.3)
                outlinePen.setColor(outlinePen.color().darker(130))
                p.setPen(outlinePen)
                bar = QRect(contentsRect.x(),
                            contentsRect.top() + 1,
                            contentsRect.width() * self._loadProgress / 100.0,
                            3)
                p.drawRoundedRect(bar, 1, 1)

    def _refreshTextFormat(self):
        if not self._webView:
            return

        textFormat = []  # typedef QList<QTextLayout::FormatRange>
        if self._webView.url().isEmpty():
            hostName = QUrl(self.text()).host()
        else:
            hostName = self._webView.url().host()

        if hostName:
            hostPos = self.text().find(hostName)
            if hostPos > 0:
                format_ = QTextCharFormat()
                palette = self.palette()
                color = Colors.mid(palette.color(QPalette.Base),
                                   palette.color(QPalette.Text), 1, 1)
                format_.setForeground(color)

                schemePart = QTextLayout.FormatRange()
                schemePart.start = 0
                schemePart.length = hostPos
                schemePart.format = format_

                hostPart = QTextLayout.FormatRange()
                hostPart.start = hostPos
                hostPart.length = len(hostName)

                remainingPart = QTextLayout.FormatRange()
                remainingPart.start = hostPos + len(hostName)
                remainingPart.length = len(self.text()) - remainingPart.start
                remainingPart.format = format_

                textFormat.append(schemePart)
                textFormat.append(hostPart)
                textFormat.append(remainingPart)

        self.setTextFormat(textFormat)
Example #18
0
 def __init__(self, parent=None, max_width=160):
     QStyledItemDelegate.__init__(self, parent)
     self.max_width = max_width
     self.dummy_model = QStringListModel([' '], self)
     self.dummy_index = self.dummy_model.index(0)
Example #19
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self._completer = None  # LocationCompleter
        self._domainCompleterModel = None  # QStringListModel

        self._bookmarkIcon = None  # BookmarksIcon
        self._goIcon = None  # GoIcon
        self._siteIcon = None  # SiteIcon
        self._autofillIcon = None  # AutoFillIcon

        self._window = None  # BrowserWindow
        self._webView = None  # TabbedWebView

        self._holdingAlt = False
        self._oldTextLength = 0
        self._currentTextLength = 0

        self._loadProgress = 0
        self._progressVisible = True
        self._progressStyle = 0  # ProgressStyle
        self._progressColor = QColor()
        self._progressTimer = None  # QTimer

        self.setObjectName('locationbar')
        self.setDragEnabled(True)

        # Disable KDE QLineEdit transitions, it breaks with setText() && home()
        self._bookmarkIcon = BookmarksIcon(self)
        self._goIcon = GoIcon(self)
        self._siteIcon = SiteIcon(self)
        self._autofillIcon = AutoFillIcon(self)
        down = DownIcon(self)

        self.addWidget(self._siteIcon, LineEdit.LeftSide)
        self.addWidget(self._autofillIcon, LineEdit.RightSide)
        self.addWidget(self._bookmarkIcon, LineEdit.RightSide)
        self.addWidget(self._goIcon, LineEdit.RightSide)
        self.addWidget(down, LineEdit.RightSide)

        self._completer = LocationCompleter(self)
        self._completer.setLocationBar(self)
        self._completer.showCompletion.connect(self._showCompletion)
        self._completer.showDomainCompletion.connect(
            self._showDomainCompletion)
        self._completer.clearCompletion.connect(self._clearCompletion)
        self._completer.loadRequested.connect(self.loadRequest)
        self._completer.popupClosed.connect(self._updateSiteIcon)

        self._domainCompleterModel = QStringListModel(self)
        domainCompleter = QCompleter(self)
        domainCompleter.setCompletionMode(QCompleter.InlineCompletion)
        domainCompleter.setModel(self._domainCompleterModel)
        self.setCompleter(domainCompleter)

        self._progressTimer = QTimer(self)
        self._progressTimer.setInterval(700)
        self._progressTimer.setSingleShot(True)
        self._progressTimer.timeout.connect(self._hideProgress)

        self.editAction(self.PasteAndGo).setText(_('Paste And &Go'))
        self.editAction(self.PasteAndGo).setIcon(QIcon.fromTheme('edit-paste'))
        self.editAction(self.PasteAndGo).triggered.connect(self._pasteAndGo)

        self.textEdited.connect(self._textEdited)
        self._goIcon.clicked.connect(self._requestLoadUrl)
        down.clicked.connect(self._completer.showMostVisited)
        # TODO:
        #gVar.app.searchEnginesManager().activeEngineChanged.connect(self._updatePlaceHolderText)
        #gVar.app.searchEnginesManager().defaultEngineChanged.connect(self._updatePlaceHolderText)

        self._loadSettings()

        self._updateSiteIcon()

        # Hide icons by default
        self._goIcon.setVisible(gVar.appSettings.alwaysShowGoIcon)
        self._autofillIcon.hide()

        QTimer.singleShot(0, self._updatePlaceHolderText)
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setEditTriggers(QAbstractItemView.NoEditTriggers)
     self.setModel(QStringListModel())
     model: QStringListModel = self.model()
Example #21
0
class FontFamilyDialog(QDialog):
    def __init__(self, current_family, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose font family'))
        self.setWindowIcon(QIcon(I('font.png')))
        from calibre.utils.fonts.scanner import font_scanner
        self.font_scanner = font_scanner

        self.m = QStringListModel(self)
        self.build_font_list()
        self.l = l = QGridLayout()
        self.setLayout(l)
        self.view = FontsView(self)
        self.view.setModel(self.m)
        self.view.setCurrentIndex(self.m.index(0))
        if current_family:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(current_family):
                    self.view.setCurrentIndex(self.m.index(i))
                    break
        self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection)
        self.view.changed.connect(self.current_changed,
                                  type=Qt.QueuedConnection)
        self.faces = Typefaces(self)
        self.bb = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        self.bb.accepted.connect(self.accept)
        self.bb.rejected.connect(self.reject)
        self.add_fonts_button = afb = self.bb.addButton(
            _('Add &fonts'), self.bb.ActionRole)
        afb.setIcon(QIcon(I('plus.png')))
        afb.clicked.connect(self.add_fonts)
        self.ml = QLabel(_('Choose a font family from the list below:'))
        self.search = QLineEdit(self)
        self.search.setPlaceholderText(_('Search'))
        self.search.returnPressed.connect(self.find)
        self.nb = QToolButton(self)
        self.nb.setIcon(QIcon(I('arrow-down.png')))
        self.nb.setToolTip(_('Find Next'))
        self.pb = QToolButton(self)
        self.pb.setIcon(QIcon(I('arrow-up.png')))
        self.pb.setToolTip(_('Find Previous'))
        self.nb.clicked.connect(self.find_next)
        self.pb.clicked.connect(self.find_previous)

        l.addWidget(self.ml, 0, 0, 1, 4)
        l.addWidget(self.search, 1, 0, 1, 1)
        l.addWidget(self.nb, 1, 1, 1, 1)
        l.addWidget(self.pb, 1, 2, 1, 1)
        l.addWidget(self.view, 2, 0, 1, 3)
        l.addWidget(self.faces, 1, 3, 2, 1)
        l.addWidget(self.bb, 3, 0, 1, 4)
        l.setAlignment(self.faces, Qt.AlignTop)

        self.resize(800, 600)

    def set_current(self, i):
        self.view.setCurrentIndex(self.m.index(i))

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Return:
            return
        return QDialog.keyPressEvent(self, e)

    def find(self, backwards=False):
        i = self.view.currentIndex().row()
        if i < 0:
            i = 0
        q = icu_lower(unicode(self.search.text())).strip()
        if not q:
            return
        r = (xrange(i - 1, -1, -1) if backwards else xrange(
            i + 1, len(self.families)))
        for j in r:
            f = self.families[j]
            if q in icu_lower(f):
                self.set_current(j)
                return

    def find_next(self):
        self.find()

    def find_previous(self):
        self.find(backwards=True)

    def build_font_list(self):
        try:
            self.families = list(self.font_scanner.find_font_families())
        except:
            self.families = []
            print('WARNING: Could not load fonts')
            import traceback
            traceback.print_exc()
        self.families.insert(0, _('None'))
        self.m.setStringList(self.families)

    def add_fonts(self):
        families = add_fonts(self)
        if not families:
            return
        self.font_scanner.do_scan()
        self.m.beginResetModel()
        self.build_font_list()
        self.m.endResetModel()
        self.view.setCurrentIndex(self.m.index(0))
        if families:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(families[0]):
                    self.view.setCurrentIndex(self.m.index(i))
                    break

        info_dialog(self,
                    _('Added fonts'),
                    _('Added font families: %s') % (', '.join(families)),
                    show=True)

    @property
    def font_family(self):
        idx = self.view.currentIndex().row()
        if idx == 0:
            return None
        return self.families[idx]

    def current_changed(self):
        fam = self.font_family
        self.faces.show_family(
            fam,
            self.font_scanner.fonts_for_family(fam) if fam else None)
Example #22
0
 def __init__(self, parent=None):
     QStyledItemDelegate.__init__(self, parent)
     self._m = QStringListModel(['sdfgkjsg sopgjs gsgs slgjslg sdklgsgl', ''])
Example #23
0
class Main(QMainWindow):
    def __init__(self): 
        global downloads_list_file
        QMainWindow.__init__(self)
        self.setWindowIcon(QIcon(":/quartz.png")) 
        self.setWindowTitle("Quartz Browser - "+__version__)
        # Window Properties
        self.history = []
        self.downloads = []
        self.confirm_before_quit = True
        # Create required directories
        for folder in [configdir, icon_dir, thumbnails_dir]:
            if not os.path.exists(folder):
                os.mkdir(folder)
        # Import and Apply Settings
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.settings = QSettings(1, 0, "quartz-browser","Quartz", self)
        self.opensettings()
        self.websettings = QWebSettings.globalSettings()
        self.websettings.setAttribute(QWebSettings.DnsPrefetchEnabled, True)
        self.websettings.setMaximumPagesInCache(10)
        self.websettings.setIconDatabasePath(icon_dir)
        self.websettings.setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
        self.websettings.setAttribute(QWebSettings.JavascriptCanCloseWindows, True)
        if webkit.enable_adblock:
            self.websettings.setUserStyleSheetUrl(QUrl.fromLocalFile(program_dir + 'userContent.css'))
        # Import Downloads and Bookmarks
        self.dwnldsmodel = DownloadsModel(self.downloads, QApplication.instance())
        self.dwnldsmodel.deleteDownloadsRequested.connect(self.deleteDownloads)
        imported_downloads = importDownloads(downloads_list_file)
        for [filepath, url, totalsize, timestamp] in imported_downloads:
            try :                                                  # Check if downloads.txt is valid
                tymstamp = float(timestamp)
            except :
                self.downloads = []
                exportDownloads(downloads_list_file, [])
                print("Error in importing Downloads.")
                break
            old_download = Download(networkmanager)
            old_download.loadDownload(filepath, url, totalsize, timestamp)
            old_download.datachanged.connect(self.dwnldsmodel.datachanged)
            self.downloads.append(old_download)
        self.bookmarks = importBookmarks(configdir+"bookmarks.txt")
        self.favourites = importFavourites(configdir + 'favourites.txt')
        # Find and set icon theme name
        for theme_name in ['Adwaita', 'Gnome', 'Tango']:
            if os.path.exists('/usr/share/icons/' + theme_name):
                QIcon.setThemeName(theme_name)
                break
        self.initUI()
        self.resize(1024,714)

    def initUI(self):
###############################  Create  Actions ##############################
        self.loadimagesaction = QAction("Load Images",self)
        self.loadimagesaction.setCheckable(True)
        self.loadimagesaction.triggered.connect(self.loadimages)

        self.javascriptmode = QAction("Enable Javascript",self)
        self.javascriptmode.setCheckable(True)
        self.javascriptmode.triggered.connect(self.setjavascript)

        self.useragent_mode_desktop = QAction("Desktop",self)
        self.useragent_mode_desktop.setCheckable(True)
        self.useragent_mode_desktop.triggered.connect(self.setUserAgentDesktop)

        self.useragent_mode_mobile = QAction("Mobile",self)
        self.useragent_mode_mobile.setCheckable(True)
        self.useragent_mode_mobile.triggered.connect(self.setUserAgentMobile)

        self.useragent_mode_custom = QAction("Custom",self)
        self.useragent_mode_custom.setCheckable(True)
        self.useragent_mode_custom.triggered.connect(self.setUserAgentCustom)

################ Add Actions to Menu ####################
        # This sub-menu sets useragent mode to desktop/mobile/custom
        self.useragentMenu = QMenu('UserAgent', self)
        self.useragentMenu.setIcon(QIcon(":/computer.png"))
        self.useragentMenu.addAction(self.useragent_mode_desktop)
        self.useragentMenu.addAction(self.useragent_mode_mobile)
        self.useragentMenu.addAction(self.useragent_mode_custom)

        # This is main menu
        self.menu = QMenu(self)
        self.menu.addAction(QIcon(":/edit-find.png"), "Find Text", self.findmode, "Ctrl+F")
        self.menu.addAction(QIcon(":/list-add.png"), "Zoom In", self.zoomin, "Ctrl++")
        self.menu.addAction(QIcon(":/list-remove.png"), "Zoom Out", self.zoomout, "Ctrl+-")
        self.menu.addAction(QIcon(":/view-fullscreen.png"), "Toggle Fullscreen", self.fullscreenmode, "F11")
        self.menu.addSeparator()

        self.menu.addAction(self.loadimagesaction)
        self.menu.addAction(self.javascriptmode)
        self.menu.addMenu(self.useragentMenu)
        self.menu.addAction(QIcon(":/applications-system.png"), "Settings", self.settingseditor, "Ctrl+,")
        self.menu.addSeparator()

        self.menu.addAction(QIcon(":/image-x-generic.png"), "Save as Image", self.saveAsImage, "Shift+Ctrl+S")
        self.menu.addAction(QIcon(":/text-html.png"), "Save as HTML", self.saveashtml, "Ctrl+S")
        self.menu.addAction(QIcon(":/document-print.png"), "Print to PDF", self.printpage, "Ctrl+P")
        self.menu.addSeparator()
        self.menu.addAction(QIcon(":/process-stop.png"), "Quit", self.forceClose, "Ctrl+Q")

        self.bmk_menu = QMenu(self)
        self.bmk_menu.addAction(QIcon(':/add-bookmark.png'), 'Add Bookmark', self.addbookmark)
        self.bmk_menu.addAction(QIcon(':/favourites.png'), 'Add to Home', self.addToFavourites)
        
###############################  Create Gui Parts ##############################
        self.centralwidget = QWidget(self)
        self.setCentralWidget(self.centralwidget)
        grid = QGridLayout(self.centralwidget)
        grid.setSpacing(1)
        grid.setContentsMargins(0,2,0,0)

        self.toolBar = QWidget(self)
        horLayout = QHBoxLayout(self.toolBar)
        horLayout.setSpacing(1)
        horLayout.setContentsMargins(0,2,0,0)

        self.addtabBtn = QPushButton(QIcon(":/add-tab.png"), "",self)
        self.addtabBtn.setToolTip("New Tab\n[Ctrl+Tab]")
        self.addtabBtn.setShortcut("Ctrl+Tab")
        self.addtabBtn.clicked.connect(self.addTab)

        self.reload = QPushButton(QIcon(":/refresh.png"), "",self) 
        self.reload.setMinimumSize(35,26) 
        self.reload.setToolTip("Reload/Stop\n  [Space]")
        self.reload.setShortcut("Space")
        self.reload.clicked.connect(self.Reload)

        self.back = QPushButton(QIcon(":/prev.png"), "", self) 
        self.back.setToolTip("Previous Page")
        self.back.setMinimumSize(35,26) 
        self.back.clicked.connect(self.Back)

        self.forw = QPushButton(QIcon(":/next.png"), "",self) 
        self.forw.setToolTip("Next Page")
        self.forw.setMinimumSize(35,26) 
        self.forw.clicked.connect(self.Forward)

        self.homeBtn = QPushButton(QIcon(":/home.png"), "",self) 
        self.homeBtn.setToolTip("Go Home")
        self.homeBtn.clicked.connect(self.goToHome)

        self.videoDownloadButton = QPushButton(QIcon(":/video-dwnld.png"), "", self)
        self.videoDownloadButton.setToolTip("Download this Video")
        self.videoDownloadButton.clicked.connect(self.downloadVideo)
        self.videoDownloadButton.hide()

        self.addbookmarkBtn = QToolButton(self)
        self.addbookmarkBtn.setIcon(QIcon(":/add-bookmark.png"))
        self.addbookmarkBtn.setToolTip("Add Bookmark")
        self.addbookmarkBtn.setMenu(self.bmk_menu)
        self.addbookmarkBtn.setPopupMode(QToolButton.InstantPopup)

        self.menuBtn = QToolButton(self)
        self.menuBtn.setIcon(QIcon(":/menu.png"))
        self.menuBtn.setMenu(self.menu)
        self.menuBtn.setPopupMode(QToolButton.InstantPopup)

        self.bookmarkBtn = QPushButton(QIcon(":/bookmarks.png"), "", self)
        self.bookmarkBtn.setToolTip("Manage Bookmarks\n         [Alt+B]")
        self.bookmarkBtn.setShortcut("Alt+B")
        self.bookmarkBtn.clicked.connect(self.managebookmarks)
        self.historyBtn = QPushButton(QIcon(":/history.png"), "", self)
        self.historyBtn.setShortcut("Alt+H")
        self.historyBtn.setToolTip("View History\n     [Alt+H]")
        self.historyBtn.clicked.connect(self.viewhistory)

        self.downloadsBtn = QPushButton(QIcon(":/download.png"), "", self)
        self.downloadsBtn.setToolTip("Download Manager")
        self.downloadsBtn.clicked.connect(self.download_manager)

        self.find = QPushButton(self)
        self.find.setText("Find/Next")
        self.find.clicked.connect(self.findnext)
        self.find.hide()
        self.findprev = QPushButton(self)
        self.findprev.setText("Backward")
        self.findprev.clicked.connect(self.findback)
        self.findprev.hide()
        self.cancelfind = QPushButton(self)
        self.cancelfind.setText("Cancel")
        self.cancelfind.clicked.connect(self.cancelfindmode)
        self.cancelfind.hide()

        self.pbar = QProgressBar(self) 
        self.pbar.setTextVisible(False)
        self.pbar.setStyleSheet("QProgressBar::chunk { background-color: #bad8ff; }")
        pbarLayout = QGridLayout(self.pbar)
        pbarLayout.setContentsMargins(0,0,0,0)

        self.line = webkit.UrlEdit(self.pbar)
        self.line.openUrlRequested.connect(self.Enter)
        self.line.textEdited.connect(self.urlsuggestions)
        self.line.downloadRequested.connect(self.download_requested_file)
        pbarLayout.addWidget(self.line)

        self.listmodel = QStringListModel(self)
        self.completer = QCompleter(self.listmodel, self.line)
        self.completer.setCompletionMode(1)
        self.completer.setMaxVisibleItems(10)
        self.line.setCompleter(self.completer)

        self.statusbar = QLabel(self)
        self.statusbar.setStyleSheet("QLabel { font-size: 12px; border-radius: 2px; padding: 2px; background: palette(highlight); color: palette(highlighted-text); }")
        self.statusbar.setMaximumHeight(16)
        self.statusbar.hide()

        self.tabWidget = QTabWidget(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.setDocumentMode(True)
        self.tabWidget.tabBar().setExpanding(True)
        self.tabWidget.tabBar().setElideMode(Qt.ElideMiddle)
        self.tabWidget.currentChanged.connect(self.onTabSwitch)
        self.tabWidget.tabCloseRequested.connect(self.closeTab)
        self.addTab()
        self.applysettings()
#       
        grid.addWidget(self.toolBar, 0,0, 1,1)
        for widget in [self.addtabBtn, self.back, self.forw, self.reload, self.homeBtn, self.videoDownloadButton,
                self.pbar, self.find, self.findprev, self.cancelfind, self.addbookmarkBtn, self.menuBtn,
                self.bookmarkBtn, self.historyBtn, self.downloadsBtn]:
            horLayout.addWidget(widget)
        grid.addWidget(self.tabWidget, 1, 0, 1, 1)

#------------------------------------------------------------------------------------------
#        Must be at the end, otherwise cause segmentation fault
#       self.status = self.statusBar() 

    def addTab(self, webview_tab=None):
        """ Creates a new tab and add to QTabWidget
            applysettings() must be called after adding each tab"""
        if not webview_tab:
            webview_tab = webkit.MyWebView(self.tabWidget, networkmanager) 
        webview_tab.windowCreated.connect(self.addTab)
        webview_tab.loadStarted.connect(self.onLoadStart) 
        webview_tab.loadFinished.connect(self.onLoadFinish) 
        webview_tab.loadProgress.connect(self.onProgress)
        webview_tab.urlChanged.connect(self.onUrlChange)
        webview_tab.titleChanged.connect(self.onTitleChange)
        webview_tab.iconChanged.connect(self.onIconChange)
        webview_tab.videoListRequested.connect(self.getVideos)
        webview_tab.page().printRequested.connect(self.printpage)
        webview_tab.page().downloadRequested.connect(self.download_requested_file)
        webview_tab.page().unsupportedContent.connect(self.handleUnsupportedContent)
        webview_tab.page().linkHovered.connect(self.onLinkHover)
        webview_tab.page().windowCloseRequested.connect(self.closeRequestedTab)

        self.tabWidget.addTab(webview_tab, "( Untitled )")
        if self.tabWidget.count()==1:
            self.tabWidget.tabBar().hide()
        else:
            self.tabWidget.tabBar().show()
        self.tabWidget.setCurrentIndex(self.tabWidget.count()-1)

    def closeTab(self, index=None):
        """ Closes tab, hides tabbar if only one tab remains"""
        if index==None:
            index = self.tabWidget.currentIndex()
        widget = self.tabWidget.widget(index)
        self.tabWidget.removeTab(index)
        widget.deleteLater()
        # Auto hide tab bar, when no. of tab widget is one
        if self.tabWidget.count()==1:
            self.tabWidget.tabBar().hide()

    def closeRequestedTab(self):
        """ Close tab requested by the page """
        webview = self.sender().view()
        index = self.tabWidget.indexOf(webview)
        self.closeTab(index)

    def Enter(self): 
        url = self.line.text()
        if url == 'about:home':
            self.goToHome()
        else:
            self.GoTo(url)

    def GoTo(self, url):
        URL = QUrl.fromUserInput(url)
        self.tabWidget.currentWidget().openLink(URL)
        self.line.setText(url)
        self.tabWidget.currentWidget().setFocus()

    def goToHome(self):
        self.GoTo(homepage)
        loop = QEventLoop()
        QTimer.singleShot(10, loop.quit)
        loop.exec_()
        document = self.tabWidget.currentWidget().page().mainFrame().documentElement()
        gallery = document.findFirst('div')
        for i, fav in enumerate(self.favourites):
            title, url, img = fav[0], fav[1], thumbnails_dir+fav[2]
            child = '<div class="photo"> <a href="{}"><img src="{}"></a><div class="desc">{}</div></div>'.format(url, img, title)
            gallery.appendInside(child)

    def onLoadStart(self):
        webview = self.sender()
        if webview is self.tabWidget.currentWidget():
          self.reload.setIcon(QIcon(":/stop.png"))

    def onProgress(self, progress):
        webview = self.sender()
        if webview is self.tabWidget.currentWidget() and webview.loading:
            self.pbar.setValue(progress)

    def onLoadFinish(self, ok):
        webview = self.sender()
        if webview is self.tabWidget.currentWidget():
          self.reload.setIcon(QIcon(":/refresh.png"))
          self.pbar.reset()
          url = self.line.text()
          self.handleVideoButton(url)

    def onTabSwitch(self, index):
        """ Updates urlbox, refresh icon, progress bar on switching tab"""
        webview = self.tabWidget.currentWidget()
        if webview.loading == True:
            self.reload.setIcon(QIcon(":/stop.png"))
            self.pbar.setValue(webview.progressVal)
        else:
            self.reload.setIcon(QIcon(":/refresh.png"))
            self.pbar.reset()
        url =  webview.url().toString()
        if url == homepage : url = 'about:home'
        self.line.setText(url)
        self.statusbar.hide()
        self.onIconChange(webview)
        self.handleVideoButton(url)

    def onUrlChange(self,url):
        url = url.toString()
        if url == homepage : url = 'about:home'
        webview = self.sender()
        if webview is self.tabWidget.currentWidget():
            self.line.setText(url)
            self.onIconChange(webview)
            self.handleVideoButton(url)

    def onTitleChange(self, title):
        webview = self.sender()
        index = self.tabWidget.indexOf(webview)
        if not title == '':
            self.tabWidget.tabBar().setTabText(index, title)
            url = webview.url().toString()
            for item in self.history:  # Removes the old item, inserts new same item on the top
                if url == item[1]:
                    self.history.remove(item)
            self.history.insert(0, [title, url])

    def onIconChange(self, webview=None):
        if not webview:
            webview = self.sender()
        icon = webview.icon()
        if icon.isNull():
            icon = QIcon(':/quartz.png')
        if webview is self.tabWidget.currentWidget():
            self.line.setIcon(icon)
        index = self.tabWidget.indexOf(webview)
        self.tabWidget.setTabIcon(index, icon)

    def onLinkHover(self, url):
        if url=="":
            self.statusbar.hide()
            return
        self.statusbar.setText(url)
        self.statusbar.adjustSize()
        self.statusbar.show()
        self.statusbar.move(QPoint(0, self.height()-self.statusbar.height()))

    def Back(self): 
        self.tabWidget.currentWidget().back() 
    def Forward(self): 
        self.tabWidget.currentWidget().forward()
    def Reload(self):
        if self.tabWidget.currentWidget().loading:
            self.tabWidget.currentWidget().stop()
        else:
            if self.line.text() == 'about:home':
                self.goToHome()
            else:
                self.tabWidget.currentWidget().reload()

    def urlsuggestions(self, text):
        """ Creates the list of url suggestions for URL box """
        suggestions = []
        if not webkit.find_mode_on:
            for [title, url] in self.history:
                if text in url:
                    suggestions.insert(0, url)
            for [title, address] in self.bookmarks:
                if text in address:
                    suggestions.insert(0, address)
        self.listmodel.setStringList( suggestions )

    def handleVideoButton(self, url):
        if youtube.validYoutubeUrl(url):
            self.videoDownloadButton.show()
            return
        frames = [self.tabWidget.currentWidget().page().mainFrame()]
        frames += frames[0].childFrames()
        for frame in frames:
            video = frame.findFirstElement('video')
            if not video.isNull():
                self.videoDownloadButton.show()
                return
        self.videoDownloadButton.hide()


##################### Downloading and Printing  ########################
    def download_requested_file(self, networkrequest):
        """ Gets called when the page requests a file to be downloaded """
        reply = networkmanager.get(networkrequest)
        self.handleUnsupportedContent(reply)

    def handleUnsupportedContent(self, reply, preset_filename=None, page_url=None):
        """ This is called when url content is a downloadable file. e.g- pdf,mp3,mp4 """
        if reply.rawHeaderList() == []:
            loop = QEventLoop()
            reply.metaDataChanged.connect(loop.quit)
            QTimer.singleShot(5000, loop.quit)
            loop.exec_()
        if reply.hasRawHeader(b'Location'):
            URL = QUrl.fromUserInput(str_(reply.rawHeader(b'Location')))
            reply.abort()
            reply = networkmanager.get(QNetworkRequest(URL))
            self.handleUnsupportedContent(reply, preset_filename)
            return
        for (title, header) in reply.rawHeaderPairs():
            print( str_(title) + "-> " + str_(header) )
        # copy url to clipboard
        QApplication.clipboard().setText(reply.url().toString())
        # Get filename and mimetype
        mimetype = None
        if reply.hasRawHeader(b'Content-Type'):
            mimetype = str_(reply.rawHeader(b'Content-Type')).split(';')[0] # eg - audio/mpeg; name=""
        content_name = str_(reply.rawHeader(b'Content-Disposition'))
        if preset_filename:
            filename = preset_filename
        else:
            filename = filenameFromHeader(content_name)
            if filename == '':
                filename = filenameFromUrl(reply.url().toString())
        filename = validateFileName(filename, mimetype)
        # Create downld Confirmation dialog
        dlDialog = DownloadDialog(self)
        dlDialog.filenameEdit.setText(filename)
        # Get filesize
        if reply.hasRawHeader(b'Content-Length'):
            filesize = reply.header(1)
            if filesize >= 1048576 :
                file_size = "{} M".format(round(float(filesize)/1048576, 2))
            elif 1023 < filesize < 1048576 :
                file_size = "{} k".format(round(float(filesize)/1024, 1))
            else:
                file_size = "{} B".format(filesize)
            dlDialog.labelFileSize.setText(file_size)
        # Get filetype and resume support info
        if mimetype:
            dlDialog.labelFileType.setText(mimetype)
        if reply.hasRawHeader(b'Accept-Ranges') or reply.hasRawHeader(b'Content-Range'):
            dlDialog.labelResume.setText("True")
        # Execute dialog and show confirmation
        if dlDialog.exec_()== QDialog.Accepted:
            filepath = dlDialog.folder + dlDialog.filenameEdit.text()
            url = reply.url().toString()
            if self.useexternaldownloader:
                download_externally(url, self.externaldownloader)
                reply.abort()
                reply.deleteLater()
                return

            global downloads_list_file
            newdownload = Download(networkmanager, page_url)
            newdownload.startDownload(reply, filepath)
            newdownload.datachanged.connect(self.dwnldsmodel.datachanged)
            self.downloads.insert(0, newdownload)
            imported_downloads = importDownloads(downloads_list_file)
            imported_downloads.insert(0, [filepath, url, str(newdownload.totalsize), newdownload.timestamp])
            exportDownloads(downloads_list_file, imported_downloads)
        else:
            reply.abort()
            reply.deleteLater()

    def download_manager(self):
        """ Opens download manager dialog """
        dialog = QDialog(self)
        downloads_dialog = Downloads_Dialog()
        downloads_dialog.setupUi(dialog, self.dwnldsmodel)
        dialog.exec_()

    def deleteDownloads(self, timestamps):
        global downloads_list_file
        imported_downloads = importDownloads(downloads_list_file)
        exported_downloads = []
        for download in imported_downloads:
            if download[-1] not in timestamps:
                exported_downloads.append(download)
        exportDownloads(downloads_list_file, exported_downloads)

    def downloadVideo(self):
        url = self.tabWidget.currentWidget().url().toString()
        # For youtube videos, parse youtube links in separate thread
        if youtube.validYoutubeUrl(url):
            vid_id = parse_qs(urlparse(url).query)['v'][0]
            ytThread = youtube.YoutubeThread(self)
            ytThread.ytParseFailed.connect(self.onYtParseFail)
            ytThread.ytVideoParsed.connect(self.onYtVideoParse)
            ytThread.finished.connect(ytThread.deleteLater)
            ytThread.vid_id = vid_id
            ytThread.start()
            return
        # For embeded HTML5 videos
        self.getVideos()

    def onYtVideoParse(self, videos):
        dialog = youtube.YoutubeDialog(videos, self)
        if dialog.exec_() == 1 :
            index = abs(dialog.buttonGroup.checkedId())-2
            vid = videos[index]
            reply = networkmanager.get( QNetworkRequest(QUrl.fromUserInput(vid.url)) )
            self.handleUnsupportedContent(reply, vid.filename + '.' + vid.extension)

    def onYtParseFail(self):
        # Show error on fail to parse youtube
        QMessageBox.warning(self, "Download Failed !","This Video can not be downloaded")

    def getVideos(self):
        dialog = youtube.Media_Dialog(self, self.tabWidget.currentWidget().page(), networkmanager)
        dialog.downloadRequested.connect(self.handleUnsupportedContent)
        dialog.exec_()

    def saveAsImage(self):
        """ Saves the whole page as PNG/JPG image"""
        title = self.tabWidget.currentWidget().page().mainFrame().title()
        title == validateFileName(title)
        filename = QFileDialog.getSaveFileName(self,
                                      "Select Image to Save", downloaddir + title +".jpg",
                                      "JPEG Image (*.jpg);;PNG Image (*.png)" )[0]
        if filename == '': return
        viewportsize = self.tabWidget.currentWidget().page().viewportSize()
        contentsize = self.tabWidget.currentWidget().page().mainFrame().contentsSize()
        self.tabWidget.currentWidget().page().setViewportSize(contentsize)
        img = QPixmap(contentsize)
        painter = QPainter(img)
        self.tabWidget.currentWidget().page().mainFrame().render(painter)
        painter.end()
        if img.save(filename):
            QMessageBox.information(self, "Successful !","Page has been successfully saved as\n"+filename)
        else:
            QMessageBox.warning(self, "Saving Failed !","Exporting page to Image hasbeen failed")
        self.tabWidget.currentWidget().page().setViewportSize(viewportsize)

    def saveashtml(self):
        """ Saves current page as HTML , bt does not saves any content (e.g images)"""
        title = self.tabWidget.currentWidget().page().mainFrame().title()
        title = validateFileName(title)
        filename = QFileDialog.getSaveFileName(self,
                                "Enter HTML File Name", downloaddir + title +".html",
                                "HTML Document (*.html)" )[0]
        if filename == '': return
        #html = self.tabWidget.currentWidget().page().mainFrame().toHtml()
        page_URL = self.tabWidget.currentWidget().url()
        useragent = self.tabWidget.currentWidget().page().userAgentForUrl(page_URL)
        doc = self.tabWidget.currentWidget().page().mainFrame().documentElement().clone()
        #doc.setInnerXml(html)
        SaveAsHtml(networkmanager, doc, filename, page_URL, useragent)

    def printpage(self, page=None):
        """ Prints current/requested page """
        if not page:
            page = self.tabWidget.currentWidget().page().currentFrame()
        printer = QPrinter(QPrinter.HighResolution)
        printer.setPaperSize(QPrinter.A4)
        printer.setPageSize(QPrinter.A4)
        printer.setColorMode(QPrinter.Color)
        printer.setCreator("Quartz Browser")
        title = self.tabWidget.currentWidget().page().mainFrame().title()
        title = validateFileName(title)
        printer.setDocName(title)
        printer.setOutputFileName(docdir + title + ".pdf")
        #printer.setOutputFormat(QPrinter.PdfFormat)
        print_dialog = QPrintPreviewDialog(printer, self)
        print_dialog.paintRequested.connect(page.print_)
        print_dialog.exec_()

##################################################################################################
    def addToFavourites(self):
        dialog = QDialog(self)
        addbmkdialog = Add_Bookmark_Dialog()
        addbmkdialog.setupUi(dialog)
        dialog.setWindowTitle('Add to HomePage')
        addbmkdialog.titleEdit.setMaxLength(31)
        addbmkdialog.titleEdit.setText(self.tabWidget.currentWidget().page().mainFrame().title())
        addbmkdialog.addressEdit.setText(self.line.text())
        if (dialog.exec_() == QDialog.Accepted):
            title = addbmkdialog.titleEdit.text()
            addr = addbmkdialog.addressEdit.text()
            imgfile = str(time.time()) + '.jpg'
            viewportsize = self.tabWidget.currentWidget().page().viewportSize()
            contentsize = QSize(640, 640)
            self.tabWidget.currentWidget().page().setViewportSize(contentsize)
            img = QPixmap(contentsize)
            painter = QPainter(img)
            self.tabWidget.currentWidget().page().mainFrame().render(painter, QWebFrame.AllLayers)
            painter.end()
            self.tabWidget.currentWidget().page().setViewportSize(viewportsize)
            icon = img.scaledToWidth(184, 1).copy(0,0, 180, 120)
            icon.save(thumbnails_dir + imgfile)
            self.favourites = importFavourites(configdir + 'favourites.txt')
            self.favourites.append([title, addr, imgfile])
            exportFavourites(configdir + 'favourites.txt', self.favourites)

    def addbookmark(self):
        """ Opens add bookmark dialog and gets url from url box"""
        dialog = QDialog(self)
        addbmkdialog = Add_Bookmark_Dialog()
        addbmkdialog.setupUi(dialog)
        addbmkdialog.titleEdit.setText(self.tabWidget.currentWidget().page().mainFrame().title())
        addbmkdialog.addressEdit.setText(self.line.text())
        if (dialog.exec_() == QDialog.Accepted):
            url = addbmkdialog.addressEdit.text()
            bmk = [addbmkdialog.titleEdit.text(), url]
            self.bookmarks = importBookmarks(configdir+"bookmarks.txt")
            self.bookmarks.insert(0, bmk)
            exportBookmarks(configdir+"bookmarks.txt", self.bookmarks)
            icon = self.tabWidget.currentWidget().icon()
            if not icon.isNull():
                icon.pixmap(16, 16).save(icon_dir + url.split('/')[2] + '.png')

    def managebookmarks(self):
        """ Opens Bookmarks dialog """
        dialog = QDialog(self)
        bmk_dialog = Bookmarks_Dialog()
        bmk_dialog.setupUi(dialog, self.bookmarks, self.favourites)
        bmk_dialog.bookmarks_table.doubleclicked.connect(self.GoTo)
        bmk_dialog.favs_table.doubleclicked.connect(self.GoTo)
        dialog.exec_()
        if bmk_dialog.bookmarks_table.data_changed:
            self.bookmarks = bmk_dialog.bookmarks_table.data
            exportBookmarks(configdir+"bookmarks.txt", self.bookmarks)
        if bmk_dialog.favs_table.data_changed:
            self.favourites = bmk_dialog.favs_table.data
            exportFavourites(configdir+"favourites.txt", self.favourites)

    def viewhistory(self):
        """ Open history dialog """
        dialog = QDialog(self)
        history_dialog = History_Dialog()
        history_dialog.setupUi(dialog, self.history)
        history_dialog.tableView.doubleclicked.connect(self.GoTo)
        dialog.exec_()

    def findmode(self):
        """ Starts find mode and unhides find buttons"""
        webkit.find_mode_on = True
        self.line.clear()
        self.find.show()
        self.findprev.show()
        self.cancelfind.show()
        self.line.setFocus()
    def cancelfindmode(self):
        """ Hides the find buttons, updates urlbox"""
        webkit.find_mode_on = False
        self.tabWidget.currentWidget().findText("")
        self.find.hide()
        self.findprev.hide()
        self.cancelfind.hide()
        self.line.setText(self.tabWidget.currentWidget().url().toString())
    def findnext(self):
        text = self.line.text()
        self.tabWidget.currentWidget().findText(text)
    def findback(self):
        text = self.line.text()
        self.tabWidget.currentWidget().findText(text, QWebPage.FindBackward)

#####################  View Settings  ###################
    def zoomin(self):
        zoomlevel = self.tabWidget.currentWidget().zoomFactor()
        self.tabWidget.currentWidget().setZoomFactor(zoomlevel+0.1) # Use setZoomFactor() to zoom text and images
    def zoomout(self):
        zoomlevel = self.tabWidget.currentWidget().zoomFactor()
        self.tabWidget.currentWidget().setZoomFactor(zoomlevel-0.1)
    def fullscreenmode(self):
        if self.isFullScreen():
            self.showNormal()
        else:
            self.showFullScreen()

    def loadimages(self, state):
        """ TOggles image loading on/off"""
        self.websettings.setAttribute(QWebSettings.AutoLoadImages, state)
        self.loadimagesval = bool(state)

    def setjavascript(self, state):
        """ Toggles js on/off """
        self.websettings.setAttribute(QWebSettings.JavascriptEnabled, state)
        self.javascriptenabledval = bool(state)

    def setUserAgentDesktop(self, checked):
        if bool(checked):
            webkit.useragent_mode = 'Desktop'
            self.useragent_mode_mobile.setChecked(False)
            self.useragent_mode_custom.setChecked(False)

    def setUserAgentMobile(self, checked):
        if bool(checked):
            webkit.useragent_mode = 'Mobile'
            self.useragent_mode_desktop.setChecked(False)
            self.useragent_mode_custom.setChecked(False)

    def setUserAgentCustom(self, checked):
        if bool(checked):
            webkit.useragent_mode = 'Custom'
            self.useragent_mode_mobile.setChecked(False)
            self.useragent_mode_desktop.setChecked(False)

########################## Settings Portion #########################
    def settingseditor(self):  
        """ Opens the settings manager dialog, then applies the change"""
        dialog = QDialog(self)
        websettingsdialog = Ui_SettingsDialog()
        websettingsdialog.setupUi(dialog)
        # Enable AdBlock
        websettingsdialog.checkAdBlock.setChecked(webkit.enable_adblock)
        # Fonts blocking
        websettingsdialog.checkFontLoad.setChecked(webkit.block_fonts)
        # Popups blocking
        websettingsdialog.checkBlockPopups.setChecked(webkit.block_popups)
        # Custom user agent
        websettingsdialog.useragentEdit.setText(webkit.useragent_custom)
        # External download manager
        websettingsdialog.checkDownMan.setChecked(self.useexternaldownloader)
        websettingsdialog.downManEdit.setText(self.externaldownloader)
        # RTSP media player command
        websettingsdialog.mediaPlayerEdit.setText(webkit.video_player_command)
        websettingsdialog.mediaPlayerEdit.setCursorPosition(0)
        # Font settings
        websettingsdialog.spinFontSize.setValue(self.minfontsizeval)
        websettingsdialog.standardfontCombo.setCurrentFont(QFont(self.standardfontval))
        websettingsdialog.sansfontCombo.setCurrentFont(QFont(self.sansfontval))
        websettingsdialog.seriffontCombo.setCurrentFont(QFont(self.seriffontval))
        websettingsdialog.fixedfontCombo.setCurrentFont(QFont(self.fixedfontval))
        # Clear Data buttons
        websettingsdialog.clearCacheButton.clicked.connect(self.websettings.clearMemoryCaches)
        websettingsdialog.cookiesButton.clicked.connect(cookiejar.clearCookies)
        websettingsdialog.iconDBButton.clicked.connect(self.websettings.clearIconDatabase)

        if dialog.exec_() == QDialog.Accepted:
            # Enable AdBlock
            webkit.enable_adblock = websettingsdialog.checkAdBlock.isChecked()
            # Block Fonts
            webkit.block_fonts = websettingsdialog.checkFontLoad.isChecked()
            # Block Popups
            webkit.block_popups = websettingsdialog.checkBlockPopups.isChecked()
            # User Agent
            webkit.useragent_custom = websettingsdialog.useragentEdit.text()
            # Download Manager
            self.useexternaldownloader = websettingsdialog.checkDownMan.isChecked()
            self.externaldownloader = websettingsdialog.downManEdit.text()
            # Media Player Command
            webkit.video_player_command = websettingsdialog.mediaPlayerEdit.text()

            self.minfontsizeval = websettingsdialog.spinFontSize.value()
            self.standardfontval = websettingsdialog.standardfontCombo.currentText()
            self.sansfontval = websettingsdialog.sansfontCombo.currentText()
            self.seriffontval = websettingsdialog.seriffontCombo.currentText()
            self.fixedfontval = websettingsdialog.fixedfontCombo.currentText()
            self.applysettings()
            self.savesettings()

    def opensettings(self): 
        """ Reads settings file in ~/.config/quartz-browser/ directory and
            saves values in settings variables"""
        webkit.enable_adblock = _bool(self.settings.value('EnableAdblock', True))
        self.loadimagesval = _bool(self.settings.value('LoadImages', True))
        self.javascriptenabledval = _bool(self.settings.value('JavaScriptEnabled', True))
        webkit.block_fonts = _bool(self.settings.value('BlockFontLoading', False))
        webkit.block_popups = _bool(self.settings.value('BlockPopups', False))
        webkit.useragent_mode = self.settings.value('UserAgentMode', webkit.useragent_mode)
        webkit.useragent_custom = self.settings.value('UserAgent', webkit.useragent_custom)
        self.useexternaldownloader = _bool(self.settings.value('UseExternalDownloader', False))
        self.externaldownloader = self.settings.value('ExternalDownloader', "x-terminal-emulator wget -c %u")
        webkit.video_player_command = self.settings.value('MediaPlayerCommand', webkit.video_player_command)
        self.maximize_window = _bool(self.settings.value('MaximizeWindow', False))
        self.minfontsizeval = int(self.settings.value('MinFontSize', 11))
        self.standardfontval = self.settings.value('StandardFont', 'Sans')
        self.sansfontval = self.settings.value('SansFont', 'Sans')
        self.seriffontval = self.settings.value('SerifFont', 'Serif')
        self.fixedfontval = self.settings.value('FixedFont', 'Monospace')

    def savesettings(self):
        """ Writes setings to disk in ~/.config/quartz-browser/ directory"""
        self.settings.setValue('EnableAdblock', webkit.enable_adblock)
        self.settings.setValue('LoadImages', self.loadimagesval)
        self.settings.setValue('JavaScriptEnabled', self.javascriptenabledval)
        self.settings.setValue('BlockFontLoading', webkit.block_fonts)
        self.settings.setValue('BlockPopups', webkit.block_popups)
        self.settings.setValue('UserAgent', webkit.useragent_custom)
        self.settings.setValue('UserAgentMode', webkit.useragent_mode)
        self.settings.setValue('UseExternalDownloader', self.useexternaldownloader)
        self.settings.setValue('ExternalDownloader', self.externaldownloader)
        self.settings.setValue('MediaPlayerCommand', webkit.video_player_command)
        self.settings.setValue('MaximizeWindow', self.isMaximized())
        self.settings.setValue('MinFontSize', self.minfontsizeval)
        self.settings.setValue('StandardFont', self.standardfontval)
        self.settings.setValue('SansFont', self.sansfontval)
        self.settings.setValue('SerifFont', self.seriffontval)
        self.settings.setValue('FixedFont', self.fixedfontval)

    def applysettings(self):
        """ Reads settings variables, and changes browser settings.This is run after
            changing settings by Settings Dialog"""
        if webkit.enable_adblock:
            self.websettings.setUserStyleSheetUrl(QUrl.fromLocalFile(program_dir + 'userContent.css'))
        else:
            self.websettings.setUserStyleSheetUrl(QUrl(''))
        self.websettings.setAttribute(QWebSettings.AutoLoadImages, self.loadimagesval)
        self.loadimagesaction.setChecked(self.loadimagesval)
        self.websettings.setAttribute(QWebSettings.JavascriptEnabled, self.javascriptenabledval)
        self.javascriptmode.setChecked(self.javascriptenabledval)
        if webkit.useragent_mode == 'Mobile':
            self.useragent_mode_mobile.setChecked(True)
        elif webkit.useragent_mode == 'Custom':
            self.useragent_mode_custom.setChecked(True)
        else:
            self.useragent_mode_desktop.setChecked(True)
        self.websettings.setFontSize(QWebSettings.MinimumFontSize, self.minfontsizeval)
        self.websettings.setFontFamily(QWebSettings.StandardFont, self.standardfontval)
        self.websettings.setFontFamily(QWebSettings.SansSerifFont, self.sansfontval)
        self.websettings.setFontFamily(QWebSettings.SerifFont, self.seriffontval)
        self.websettings.setFontFamily(QWebSettings.FixedFont, self.fixedfontval)
#        self.websettings.setFontSize(QWebSettings.DefaultFontSize, 14)

    def enableKiosk(self):
        webkit.KIOSK_MODE = True
        self.menu.clear()
        self.toolBar.hide()
        self.showFullScreen()

    def forceClose(self):
        self.confirm_before_quit = False
        self.close()

    def closeEvent(self, event):
        """This saves all settings, bookmarks, cookies etc. during window close"""
        if self.confirm_before_quit:
            confirm = QMessageBox.warning(self, 'Quit Browser ?', 'Are you sure to close the Browser',
                                                QMessageBox.Yes|QMessageBox.No, QMessageBox.Yes)
            if confirm == QMessageBox.No :
                event.ignore()
                return
        self.savesettings()
        cookiejar.exportCookies()
        # Delete excess thumbnails
        thumbnails = [ x for x in os.listdir(thumbnails_dir) ]
        for fav in self.favourites:
            if fav[2] in thumbnails:
                thumbnails.remove(fav[2])
        for f in thumbnails: os.remove(thumbnails_dir + f)
        # Delete excess icons
        icons = [ x for x in os.listdir(icon_dir) if x.endswith('.png') ]
        for bmk in self.bookmarks:
            host = QUrl(bmk[1]).host()
            if host + '.png' in icons:
                icons.remove(host + '.png')
        for f in icons: os.remove( icon_dir + f )
        super(Main, self).closeEvent(event)
Example #24
0
 def __init__(self, widgets):
     QStringListModel.__init__(self)
     self.widgets = widgets
     self.setStringList([w.TITLE for w in widgets])
Example #25
0
class OpdsDialog(QDialog):

    def __init__(self, gui, icon, do_user_config):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config

        self.db = gui.current_db.new_api

        # The model for the book list
        self.model = OpdsBooksModel(None, self.dummy_books(), self.db)
        self.searchproxymodel = QSortFilterProxyModel(self)
        self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.searchproxymodel.setFilterKeyColumn(-1)
        self.searchproxymodel.setSourceModel(self.model)

        self.layout = QGridLayout()
        self.setLayout(self.layout)

        self.setWindowTitle('OPDS Client')
        self.setWindowIcon(icon)

        labelColumnWidths = []

        self.opdsUrlLabel = QLabel('OPDS URL: ')
        self.layout.addWidget(self.opdsUrlLabel, 0, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width())

        config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference()
        self.opdsUrlEditor = QComboBox(self)
        self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated)
        self.opdsUrlEditor.addItems(prefs['opds_url'])
        self.opdsUrlEditor.setEditable(True)
        self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop)
        self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3)
        self.opdsUrlLabel.setBuddy(self.opdsUrlEditor)

        buttonColumnNumber = 7
        buttonColumnWidths = []
        self.about_button = QPushButton('About', self)
        self.about_button.setAutoDefault(False)
        self.about_button.clicked.connect(self.about)
        self.layout.addWidget(self.about_button, 0, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width()) 

        # Initially download the catalogs found in the root catalog of the URL
        # selected at startup.  Fail quietly on failing to open the URL
        catalogsTuple = self.model.downloadOpdsRootCatalog(self.gui, self.opdsUrlEditor.currentText(), False)
        print catalogsTuple
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL

        self.opdsCatalogSelectorLabel = QLabel('OPDS Catalog:')
        self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width())

        self.opdsCatalogSelector = QComboBox(self)
        self.opdsCatalogSelector.setEditable(False)
        self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel)
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)
        self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3)

        self.download_opds_button = QPushButton('Download OPDS', self)
        self.download_opds_button.setAutoDefault(False)
        self.download_opds_button.clicked.connect(self.download_opds)
        self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width()) 

        # Search GUI
        self.searchEditor = QLineEdit(self)
        self.searchEditor.returnPressed.connect(self.searchBookList)
        self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2)

        self.searchButton = QPushButton('Search', self)
        self.searchButton.setAutoDefault(False)
        self.searchButton.clicked.connect(self.searchBookList)
        self.layout.addWidget(self.searchButton, 2, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width())

        # The main book list
        self.library_view = QTableView(self)
        self.library_view.setAlternatingRowColors(True)
        self.library_view.setModel(self.searchproxymodel)
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.library_view.resizeColumnsToContents()
        self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1)

        self.hideNewsCheckbox = QCheckBox('Hide Newspapers', self)
        self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers)
        self.hideNewsCheckbox.setChecked(prefs['hideNewspapers'])
        self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3)

        self.hideBooksAlreadyInLibraryCheckbox = QCheckBox('Hide books already in library', self)
        self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary)
        self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs['hideBooksAlreadyInLibrary'])
        self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3)

        # Let the checkbox initial state control the filtering
        self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked())
        self.model.setFilterBooksThatAreAlreadyInLibrary(self.hideBooksAlreadyInLibraryCheckbox.isChecked())

        self.downloadButton = QPushButton('Download selected books', self)
        self.downloadButton.setAutoDefault(False)
        self.downloadButton.clicked.connect(self.downloadSelectedBooks)
        self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width()) 

        self.fixTimestampButton = QPushButton('Fix timestamps of selection', self)
        self.fixTimestampButton.setAutoDefault(False)
        self.fixTimestampButton.clicked.connect(self.fixBookTimestamps)
        self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width()) 

        # Make all columns of the grid layout the same width as the button column
        buttonColumnWidth = max(buttonColumnWidths)
        for columnNumber in range(0, buttonColumnNumber):
            self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth)

        # Make sure the first column isn't wider than the labels it holds
        labelColumnWidth = max(labelColumnWidths)
        self.layout.setColumnMinimumWidth(0, labelColumnWidth)

        self.resize(self.sizeHint())

    def opdsUrlEditorActivated(self, text):
        prefs['opds_url'] = config.saveOpdsUrlCombobox(self.opdsUrlEditor)
        catalogsTuple = self.model.downloadOpdsRootCatalog(self.gui, self.opdsUrlEditor.currentText(), True)
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL
        self.opdsCatalogSelectorModel.setStringList(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)

    def setHideNewspapers(self, checked):
        prefs['hideNewspapers'] = checked
        self.model.setFilterBooksThatAreNewspapers(checked)
        self.resizeAllLibraryViewLinesToHeaderHeight()

    def setHideBooksAlreadyInLibrary(self, checked):
        prefs['hideBooksAlreadyInLibrary'] = checked
        self.model.setFilterBooksThatAreAlreadyInLibrary(checked)
        self.resizeAllLibraryViewLinesToHeaderHeight()

    def searchBookList(self):
        searchString = self.searchEditor.text()
        print "starting book list search for: %s" % searchString
        self.searchproxymodel.setFilterFixedString(searchString)

    def about(self):
        text = get_resources('about.txt')
        QMessageBox.about(self, 'About the OPDS Client plugin', text.decode('utf-8'))

    def download_opds(self):
        opdsCatalogUrl = self.currentOpdsCatalogs.get(self.opdsCatalogSelector.currentText(), None)
        if opdsCatalogUrl is None:
            # Just give up quietly
            return
        self.model.downloadOpdsCatalog(self.gui, opdsCatalogUrl)
        if self.model.isCalibreOpdsServer():
            self.model.downloadMetadataUsingCalibreRestApi(self.opdsUrlEditor.currentText())
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.resize(self.sizeHint())

    def config(self):
        self.do_user_config(parent=self)

    def downloadSelectedBooks(self):
        selectionmodel = self.library_view.selectionModel()
        if selectionmodel.hasSelection():
            rows = selectionmodel.selectedRows()
            for row in reversed(rows):
                book = row.data(Qt.UserRole)
                self.downloadBook(book)

    def downloadBook(self, book):
        if len(book.links) > 0:
            self.gui.download_ebook(book.links[0])

    def fixBookTimestamps(self):
        selectionmodel = self.library_view.selectionModel()
        if selectionmodel.hasSelection():
            rows = selectionmodel.selectedRows()
            for row in reversed(rows):
                book = row.data(Qt.UserRole)
                self.fixBookTimestamp(book)

    def fixBookTimestamp(self, book):
        bookTimestamp = book.timestamp
        identicalBookIds = self.findIdenticalBooksForBooksWithMultipleAuthors(book)
        bookIdToValMap = {}
        for identicalBookId in identicalBookIds:
            bookIdToValMap[identicalBookId] = bookTimestamp
        if len(bookIdToValMap) < 1:
            print "Failed to set timestamp of book: %s" % book
        self.db.set_field('timestamp', bookIdToValMap)

    def findIdenticalBooksForBooksWithMultipleAuthors(self, book):
        authorsList = book.authors
        if len(authorsList) < 2:
            return self.db.find_identical_books(book)
        # Try matching the authors one by one
        identicalBookIds = set()
        for author in authorsList:
            singleAuthorBook = Metadata(book.title, [author])
            singleAuthorIdenticalBookIds = self.db.find_identical_books(singleAuthorBook)
            identicalBookIds = identicalBookIds.union(singleAuthorIdenticalBookIds)
        return identicalBookIds

    def dummy_books(self):
        dummy_author = ' ' * 40
        dummy_title = ' ' * 60
        books_list = []
        for line in range (1, 10):
            book = DynamicBook()
            book.author = dummy_author
            book.title = dummy_title
            book.updated = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S+00:00')
            book.id = ''
            books_list.append(book)
        return books_list

    def resizeAllLibraryViewLinesToHeaderHeight(self):
        rowHeight = self.library_view.horizontalHeader().height()
        for rowNumber in range (0, self.library_view.model().rowCount()):
            self.library_view.setRowHeight(rowNumber, rowHeight)
Example #26
0
    def __init__(self, gui, icon, do_user_config):
        QDialog.__init__(self, gui)
        self.gui = gui
        self.do_user_config = do_user_config

        self.db = gui.current_db.new_api

        # The model for the book list
        self.model = OpdsBooksModel(None, self.dummy_books(), self.db)
        self.searchproxymodel = QSortFilterProxyModel(self)
        self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.searchproxymodel.setFilterKeyColumn(-1)
        self.searchproxymodel.setSourceModel(self.model)

        self.layout = QGridLayout()
        self.setLayout(self.layout)

        self.setWindowTitle('OPDS Client')
        self.setWindowIcon(icon)

        labelColumnWidths = []

        self.opdsUrlLabel = QLabel('OPDS URL: ')
        self.layout.addWidget(self.opdsUrlLabel, 0, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width())

        config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference()
        self.opdsUrlEditor = QComboBox(self)
        self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated)
        self.opdsUrlEditor.addItems(prefs['opds_url'])
        self.opdsUrlEditor.setEditable(True)
        self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop)
        self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3)
        self.opdsUrlLabel.setBuddy(self.opdsUrlEditor)

        buttonColumnNumber = 7
        buttonColumnWidths = []
        self.about_button = QPushButton('About', self)
        self.about_button.setAutoDefault(False)
        self.about_button.clicked.connect(self.about)
        self.layout.addWidget(self.about_button, 0, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width()) 

        # Initially download the catalogs found in the root catalog of the URL
        # selected at startup.  Fail quietly on failing to open the URL
        catalogsTuple = self.model.downloadOpdsRootCatalog(self.gui, self.opdsUrlEditor.currentText(), False)
        print catalogsTuple
        firstCatalogTitle = catalogsTuple[0]
        self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL

        self.opdsCatalogSelectorLabel = QLabel('OPDS Catalog:')
        self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0)
        labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width())

        self.opdsCatalogSelector = QComboBox(self)
        self.opdsCatalogSelector.setEditable(False)
        self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys())
        self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel)
        self.opdsCatalogSelector.setCurrentText(firstCatalogTitle)
        self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3)

        self.download_opds_button = QPushButton('Download OPDS', self)
        self.download_opds_button.setAutoDefault(False)
        self.download_opds_button.clicked.connect(self.download_opds)
        self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width()) 

        # Search GUI
        self.searchEditor = QLineEdit(self)
        self.searchEditor.returnPressed.connect(self.searchBookList)
        self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2)

        self.searchButton = QPushButton('Search', self)
        self.searchButton.setAutoDefault(False)
        self.searchButton.clicked.connect(self.searchBookList)
        self.layout.addWidget(self.searchButton, 2, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width())

        # The main book list
        self.library_view = QTableView(self)
        self.library_view.setAlternatingRowColors(True)
        self.library_view.setModel(self.searchproxymodel)
        self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.resizeAllLibraryViewLinesToHeaderHeight()
        self.library_view.resizeColumnsToContents()
        self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1)

        self.hideNewsCheckbox = QCheckBox('Hide Newspapers', self)
        self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers)
        self.hideNewsCheckbox.setChecked(prefs['hideNewspapers'])
        self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3)

        self.hideBooksAlreadyInLibraryCheckbox = QCheckBox('Hide books already in library', self)
        self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary)
        self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs['hideBooksAlreadyInLibrary'])
        self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3)

        # Let the checkbox initial state control the filtering
        self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked())
        self.model.setFilterBooksThatAreAlreadyInLibrary(self.hideBooksAlreadyInLibraryCheckbox.isChecked())

        self.downloadButton = QPushButton('Download selected books', self)
        self.downloadButton.setAutoDefault(False)
        self.downloadButton.clicked.connect(self.downloadSelectedBooks)
        self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width()) 

        self.fixTimestampButton = QPushButton('Fix timestamps of selection', self)
        self.fixTimestampButton.setAutoDefault(False)
        self.fixTimestampButton.clicked.connect(self.fixBookTimestamps)
        self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber)
        buttonColumnWidths.append(self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width()) 

        # Make all columns of the grid layout the same width as the button column
        buttonColumnWidth = max(buttonColumnWidths)
        for columnNumber in range(0, buttonColumnNumber):
            self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth)

        # Make sure the first column isn't wider than the labels it holds
        labelColumnWidth = max(labelColumnWidths)
        self.layout.setColumnMinimumWidth(0, labelColumnWidth)

        self.resize(self.sizeHint())
Example #27
0
class FontFamilyDialog(QDialog):

    def __init__(self, current_family, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Choose font family'))
        self.setWindowIcon(QIcon(I('font.png')))
        from calibre.utils.fonts.scanner import font_scanner
        self.font_scanner = font_scanner

        self.m = QStringListModel(self)
        self.build_font_list()
        self.l = l = QGridLayout()
        self.setLayout(l)
        self.view = FontsView(self)
        self.view.setModel(self.m)
        self.view.setCurrentIndex(self.m.index(0))
        if current_family:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(current_family):
                    self.view.setCurrentIndex(self.m.index(i))
                    break
        self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection)
        self.view.changed.connect(self.current_changed,
                type=Qt.QueuedConnection)
        self.faces = Typefaces(self)
        self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        self.bb.accepted.connect(self.accept)
        self.bb.rejected.connect(self.reject)
        self.add_fonts_button = afb = self.bb.addButton(_('Add &fonts'),
                self.bb.ActionRole)
        afb.setIcon(QIcon(I('plus.png')))
        afb.clicked.connect(self.add_fonts)
        self.ml = QLabel(_('Choose a font family from the list below:'))
        self.search = QLineEdit(self)
        self.search.setPlaceholderText(_('Search'))
        self.search.returnPressed.connect(self.find)
        self.nb = QToolButton(self)
        self.nb.setIcon(QIcon(I('arrow-down.png')))
        self.nb.setToolTip(_('Find next'))
        self.pb = QToolButton(self)
        self.pb.setIcon(QIcon(I('arrow-up.png')))
        self.pb.setToolTip(_('Find previous'))
        self.nb.clicked.connect(self.find_next)
        self.pb.clicked.connect(self.find_previous)

        l.addWidget(self.ml, 0, 0, 1, 4)
        l.addWidget(self.search, 1, 0, 1, 1)
        l.addWidget(self.nb, 1, 1, 1, 1)
        l.addWidget(self.pb, 1, 2, 1, 1)
        l.addWidget(self.view, 2, 0, 1, 3)
        l.addWidget(self.faces, 1, 3, 2, 1)
        l.addWidget(self.bb, 3, 0, 1, 4)
        l.setAlignment(self.faces, Qt.AlignTop)

        self.resize(800, 600)

    def set_current(self, i):
        self.view.setCurrentIndex(self.m.index(i))

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Return:
            return
        return QDialog.keyPressEvent(self, e)

    def find(self, backwards=False):
        i = self.view.currentIndex().row()
        if i < 0:
            i = 0
        q = icu_lower(unicode(self.search.text())).strip()
        if not q:
            return
        r = (xrange(i-1, -1, -1) if backwards else xrange(i+1,
            len(self.families)))
        for j in r:
            f = self.families[j]
            if q in icu_lower(f):
                self.set_current(j)
                return

    def find_next(self):
        self.find()

    def find_previous(self):
        self.find(backwards=True)

    def build_font_list(self):
        try:
            self.families = list(self.font_scanner.find_font_families())
        except:
            self.families = []
            print ('WARNING: Could not load fonts')
            import traceback
            traceback.print_exc()
        self.families.insert(0, _('None'))
        self.m.setStringList(self.families)

    def add_fonts(self):
        families = add_fonts(self)
        if not families:
            return
        self.font_scanner.do_scan()
        self.m.beginResetModel()
        self.build_font_list()
        self.m.endResetModel()
        self.view.setCurrentIndex(self.m.index(0))
        if families:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(families[0]):
                    self.view.setCurrentIndex(self.m.index(i))
                    break

        info_dialog(self, _('Added fonts'),
                _('Added font families: %s')%(
                    ', '.join(families)), show=True)

    @property
    def font_family(self):
        idx = self.view.currentIndex().row()
        if idx == 0:
            return None
        return self.families[idx]

    def current_changed(self):
        fam = self.font_family
        self.faces.show_family(fam, self.font_scanner.fonts_for_family(fam)
                if fam else None)
Example #28
0
    settings = qwebpage_or_qwebsettings if isinstance(qwebpage_or_qwebsettings, QWebSettings) else qwebpage_or_qwebsettings.settings()
    settings.setAttribute(QWebSettings.JavaEnabled, False)
    settings.setAttribute(QWebSettings.PluginsEnabled, False)
    settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
    settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False)
    settings.setAttribute(QWebSettings.LocalContentCanAccessFileUrls, False)  # ensure javascript cannot read from local files
    settings.setAttribute(QWebSettings.NotificationsEnabled, False)
    settings.setThirdPartyCookiePolicy(QWebSettings.AlwaysBlockThirdPartyCookies)
    settings.setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, False)
    settings.setAttribute(QWebSettings.LocalStorageEnabled, False)
    QWebSettings.setOfflineStorageDefaultQuota(0)
    QWebSettings.setOfflineStoragePath(None)
    return settings


empty_model = QStringListModel([''])
empty_index = empty_model.index(0)


def get_app_uid():
    import ctypes
    from ctypes import wintypes
    lpBuffer = wintypes.LPWSTR()
    try:
        AppUserModelID = ctypes.windll.shell32.GetCurrentProcessExplicitAppUserModelID
    except Exception:  # Vista has no app uids
        return
    AppUserModelID.argtypes = [wintypes.LPWSTR]
    AppUserModelID.restype = wintypes.HRESULT
    try:
        AppUserModelID(ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR))
Example #29
0
class SideView(QObject):
    onBeforeItemDeletion = pyqtSignal(str)
    onEntrySelected = pyqtSignal(str)
    onDirectoryChanged = pyqtSignal(str)
    onRemoveRequested = pyqtSignal(str)

    def __init__(self, dirLister, entryProvider: IEntryProvider,
                 newEntryText: str, itemNameNormalizer: IItemNameNormalizer):
        super().__init__()

        def initListView():
            self.listView = QListView()
            self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            self.listView.setModel(self.model)
            self.listView.setMinimumWidth(200)

            actionRemove = QAction("Remove", None)
            self.listView.addAction(actionRemove)

            self.listView.selectionModel().currentChanged.connect(
                lambda selectedItem, unselectedItem: self.onEntrySelected.emit(
                    self.itemNameNormalizer.normalizeName(
                        self.currentDir.filePath(selectedItem.data()))))

            def contextMenu(position):
                menu = QMenu()
                index = self.listView.indexAt(position)
                entry = self.model.data(index, Qt.DisplayRole)

                deleteAction = None
                renameAction = None

                addAction = menu.addAction("Add")

                if entry is not None:
                    deleteAction = menu.addAction("Delete")
                    renameAction = menu.addAction("Rename")

                refreshAction = menu.addAction("Refresh")

                chosenAction = menu.exec_(self.listView.mapToGlobal(position))

                if chosenAction is None:
                    return

                if chosenAction == deleteAction:
                    self.onRemoveRequested.emit(entry)
                elif chosenAction == renameAction:
                    self.renameEntry(index, entry)
                elif chosenAction == addAction:
                    self.onCreateNewEntry()
                elif chosenAction == refreshAction:
                    self.refreshListViewEntries()

            self.listView.customContextMenuRequested.connect(contextMenu)
            self.listView.setContextMenuPolicy(Qt.CustomContextMenu)

        self.currentDir: QDir = None
        self.model = QStringListModel()
        self.directoryLister = dirLister
        self.entryProvider = entryProvider
        self.newEntryText = newEntryText
        self.itemNameNormalizer = itemNameNormalizer
        self.sortingParser: IEntrySorting
        initListView()

    def renameEntry(self, index, oldName):
        def onNewEntryCommited(editedLine: QLineEdit):
            self.listView.itemDelegate().commitData.disconnect(
                onNewEntryCommited)
            try:
                newName = editedLine.text()
                normalizedNameOld = self.itemNameNormalizer.normalizeName(
                    oldName)
                normalizedNameNew = self.itemNameNormalizer.normalizeName(
                    newName)

                self.emitOnItemDeletion(normalizedNameOld)

                self.entryProvider.renameEnty(normalizedNameOld,
                                              normalizedNameNew)
                self.sortingParser.rename(oldName, newName)
                self.refreshListViewEntries()
            except Exception:
                pass

        self.listView.itemDelegate().commitData.connect(onNewEntryCommited)
        self.listView.edit(index)

    def emitOnItemDeletion(self, normalizedName):
        self.onBeforeItemDeletion.emit(
            self.currentDir.filePath(normalizedName))

    def removeEntry(self, entry):
        normalizedName = self.itemNameNormalizer.normalizeName(entry)
        self.emitOnItemDeletion(normalizedName)

        self.entryProvider.removeEntry(normalizedName)
        self.refreshListViewEntries()

    def setDirectory(self, dirPath: str):
        self.currentDir = QDir(dirPath)
        self.sortingParser = EntrySortingFile(
            self.currentDir.filePath('.sorting'))
        self.entryProvider.setContext(dirPath)
        self.refreshListViewEntries()

        self.onDirectoryChanged.emit(self.currentDir.absolutePath())

    def refreshListViewEntries(self):
        if self.currentDir is None:
            return
        entries = self.directoryLister.listEntries(self.currentDir)
        sortedEntries = self.sortingParser.getSortedList(entries)

        self.model.setStringList(sortedEntries)

    def onCreateNewEntry(self):
        def onNewEntryCommited(editedLine: QLineEdit):
            self.listView.itemDelegate().commitData.disconnect(
                onNewEntryCommited)
            try:
                if editedLine.text() == self.newEntryText:
                    raise Exception()

                normalizedName = self.itemNameNormalizer.normalizeName(
                    editedLine.text())
                self.entryProvider.addEntry(normalizedName)
                self.refreshListViewEntries()
                self.listView.setCurrentIndex(index)
            except Exception:
                print(f"Error adding entry {editedLine.text()}",
                      file=sys.stderr)
                self.model.removeRow(self.model.rowCount() - 1)

        if not self.model.insertRow(self.model.rowCount()):
            return

        self.listView.itemDelegate().commitData.connect(onNewEntryCommited)
        index = self.model.index(self.model.rowCount() - 1, 0)
        self.model.setData(index, self.newEntryText)
        self.listView.edit(index)
        pass
Example #30
0
File: ask.py Project: alok/vise
 def __init__(self, parent=None):
     QStyledItemDelegate.__init__(self, parent)
     self._m = QStringListModel(
         ['sdfgkjsg sopgjs gsgs slgjslg sdklgsgl', ''])
Example #31
0
 def __init__(self, widgets):
     QStringListModel.__init__(self)
     self.widgets = widgets
     self.setStringList([w.TITLE for w in widgets])
Example #32
0
 def update_items_cache(self, items):
     self.all_items = set(items)
     model = QStringListModel(items, self)
     self.setModel(model)
Example #33
0
 def data(self, index, role):
     if role == Qt.DecorationRole:
         w = self.widgets[index.row()]
         if w.ICON:
             return (QIcon(w.ICON))
     return QStringListModel.data(self, index, role)
Example #34
0
 def data(self, index, role):
     if role == Qt.DecorationRole:
         w = self.widgets[index.row()]
         if w.ICON:
             return (QIcon(w.ICON))
     return QStringListModel.data(self, index, role)
Example #35
0
 def __init__(self, values):
     QStringListModel.__init__(self, values)
Example #36
0
    def initUI(self):
###############################  Create  Actions ##############################
        self.loadimagesaction = QAction("Load Images",self)
        self.loadimagesaction.setCheckable(True)
        self.loadimagesaction.triggered.connect(self.loadimages)

        self.javascriptmode = QAction("Enable Javascript",self)
        self.javascriptmode.setCheckable(True)
        self.javascriptmode.triggered.connect(self.setjavascript)

        self.useragent_mode_desktop = QAction("Desktop",self)
        self.useragent_mode_desktop.setCheckable(True)
        self.useragent_mode_desktop.triggered.connect(self.setUserAgentDesktop)

        self.useragent_mode_mobile = QAction("Mobile",self)
        self.useragent_mode_mobile.setCheckable(True)
        self.useragent_mode_mobile.triggered.connect(self.setUserAgentMobile)

        self.useragent_mode_custom = QAction("Custom",self)
        self.useragent_mode_custom.setCheckable(True)
        self.useragent_mode_custom.triggered.connect(self.setUserAgentCustom)

################ Add Actions to Menu ####################
        # This sub-menu sets useragent mode to desktop/mobile/custom
        self.useragentMenu = QMenu('UserAgent', self)
        self.useragentMenu.setIcon(QIcon(":/computer.png"))
        self.useragentMenu.addAction(self.useragent_mode_desktop)
        self.useragentMenu.addAction(self.useragent_mode_mobile)
        self.useragentMenu.addAction(self.useragent_mode_custom)

        # This is main menu
        self.menu = QMenu(self)
        self.menu.addAction(QIcon(":/edit-find.png"), "Find Text", self.findmode, "Ctrl+F")
        self.menu.addAction(QIcon(":/list-add.png"), "Zoom In", self.zoomin, "Ctrl++")
        self.menu.addAction(QIcon(":/list-remove.png"), "Zoom Out", self.zoomout, "Ctrl+-")
        self.menu.addAction(QIcon(":/view-fullscreen.png"), "Toggle Fullscreen", self.fullscreenmode, "F11")
        self.menu.addSeparator()

        self.menu.addAction(self.loadimagesaction)
        self.menu.addAction(self.javascriptmode)
        self.menu.addMenu(self.useragentMenu)
        self.menu.addAction(QIcon(":/applications-system.png"), "Settings", self.settingseditor, "Ctrl+,")
        self.menu.addSeparator()

        self.menu.addAction(QIcon(":/image-x-generic.png"), "Save as Image", self.saveAsImage, "Shift+Ctrl+S")
        self.menu.addAction(QIcon(":/text-html.png"), "Save as HTML", self.saveashtml, "Ctrl+S")
        self.menu.addAction(QIcon(":/document-print.png"), "Print to PDF", self.printpage, "Ctrl+P")
        self.menu.addSeparator()
        self.menu.addAction(QIcon(":/process-stop.png"), "Quit", self.forceClose, "Ctrl+Q")

        self.bmk_menu = QMenu(self)
        self.bmk_menu.addAction(QIcon(':/add-bookmark.png'), 'Add Bookmark', self.addbookmark)
        self.bmk_menu.addAction(QIcon(':/favourites.png'), 'Add to Home', self.addToFavourites)
        
###############################  Create Gui Parts ##############################
        self.centralwidget = QWidget(self)
        self.setCentralWidget(self.centralwidget)
        grid = QGridLayout(self.centralwidget)
        grid.setSpacing(1)
        grid.setContentsMargins(0,2,0,0)

        self.toolBar = QWidget(self)
        horLayout = QHBoxLayout(self.toolBar)
        horLayout.setSpacing(1)
        horLayout.setContentsMargins(0,2,0,0)

        self.addtabBtn = QPushButton(QIcon(":/add-tab.png"), "",self)
        self.addtabBtn.setToolTip("New Tab\n[Ctrl+Tab]")
        self.addtabBtn.setShortcut("Ctrl+Tab")
        self.addtabBtn.clicked.connect(self.addTab)

        self.reload = QPushButton(QIcon(":/refresh.png"), "",self) 
        self.reload.setMinimumSize(35,26) 
        self.reload.setToolTip("Reload/Stop\n  [Space]")
        self.reload.setShortcut("Space")
        self.reload.clicked.connect(self.Reload)

        self.back = QPushButton(QIcon(":/prev.png"), "", self) 
        self.back.setToolTip("Previous Page")
        self.back.setMinimumSize(35,26) 
        self.back.clicked.connect(self.Back)

        self.forw = QPushButton(QIcon(":/next.png"), "",self) 
        self.forw.setToolTip("Next Page")
        self.forw.setMinimumSize(35,26) 
        self.forw.clicked.connect(self.Forward)

        self.homeBtn = QPushButton(QIcon(":/home.png"), "",self) 
        self.homeBtn.setToolTip("Go Home")
        self.homeBtn.clicked.connect(self.goToHome)

        self.videoDownloadButton = QPushButton(QIcon(":/video-dwnld.png"), "", self)
        self.videoDownloadButton.setToolTip("Download this Video")
        self.videoDownloadButton.clicked.connect(self.downloadVideo)
        self.videoDownloadButton.hide()

        self.addbookmarkBtn = QToolButton(self)
        self.addbookmarkBtn.setIcon(QIcon(":/add-bookmark.png"))
        self.addbookmarkBtn.setToolTip("Add Bookmark")
        self.addbookmarkBtn.setMenu(self.bmk_menu)
        self.addbookmarkBtn.setPopupMode(QToolButton.InstantPopup)

        self.menuBtn = QToolButton(self)
        self.menuBtn.setIcon(QIcon(":/menu.png"))
        self.menuBtn.setMenu(self.menu)
        self.menuBtn.setPopupMode(QToolButton.InstantPopup)

        self.bookmarkBtn = QPushButton(QIcon(":/bookmarks.png"), "", self)
        self.bookmarkBtn.setToolTip("Manage Bookmarks\n         [Alt+B]")
        self.bookmarkBtn.setShortcut("Alt+B")
        self.bookmarkBtn.clicked.connect(self.managebookmarks)
        self.historyBtn = QPushButton(QIcon(":/history.png"), "", self)
        self.historyBtn.setShortcut("Alt+H")
        self.historyBtn.setToolTip("View History\n     [Alt+H]")
        self.historyBtn.clicked.connect(self.viewhistory)

        self.downloadsBtn = QPushButton(QIcon(":/download.png"), "", self)
        self.downloadsBtn.setToolTip("Download Manager")
        self.downloadsBtn.clicked.connect(self.download_manager)

        self.find = QPushButton(self)
        self.find.setText("Find/Next")
        self.find.clicked.connect(self.findnext)
        self.find.hide()
        self.findprev = QPushButton(self)
        self.findprev.setText("Backward")
        self.findprev.clicked.connect(self.findback)
        self.findprev.hide()
        self.cancelfind = QPushButton(self)
        self.cancelfind.setText("Cancel")
        self.cancelfind.clicked.connect(self.cancelfindmode)
        self.cancelfind.hide()

        self.pbar = QProgressBar(self) 
        self.pbar.setTextVisible(False)
        self.pbar.setStyleSheet("QProgressBar::chunk { background-color: #bad8ff; }")
        pbarLayout = QGridLayout(self.pbar)
        pbarLayout.setContentsMargins(0,0,0,0)

        self.line = webkit.UrlEdit(self.pbar)
        self.line.openUrlRequested.connect(self.Enter)
        self.line.textEdited.connect(self.urlsuggestions)
        self.line.downloadRequested.connect(self.download_requested_file)
        pbarLayout.addWidget(self.line)

        self.listmodel = QStringListModel(self)
        self.completer = QCompleter(self.listmodel, self.line)
        self.completer.setCompletionMode(1)
        self.completer.setMaxVisibleItems(10)
        self.line.setCompleter(self.completer)

        self.statusbar = QLabel(self)
        self.statusbar.setStyleSheet("QLabel { font-size: 12px; border-radius: 2px; padding: 2px; background: palette(highlight); color: palette(highlighted-text); }")
        self.statusbar.setMaximumHeight(16)
        self.statusbar.hide()

        self.tabWidget = QTabWidget(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.setDocumentMode(True)
        self.tabWidget.tabBar().setExpanding(True)
        self.tabWidget.tabBar().setElideMode(Qt.ElideMiddle)
        self.tabWidget.currentChanged.connect(self.onTabSwitch)
        self.tabWidget.tabCloseRequested.connect(self.closeTab)
        self.addTab()
        self.applysettings()
#       
        grid.addWidget(self.toolBar, 0,0, 1,1)
        for widget in [self.addtabBtn, self.back, self.forw, self.reload, self.homeBtn, self.videoDownloadButton,
                self.pbar, self.find, self.findprev, self.cancelfind, self.addbookmarkBtn, self.menuBtn,
                self.bookmarkBtn, self.historyBtn, self.downloadsBtn]:
            horLayout.addWidget(widget)
        grid.addWidget(self.tabWidget, 1, 0, 1, 1)
Example #37
0
 def data(self, index, role):
     return QStringListModel.data(self, index, Qt.DisplayRole if role == Qt.ToolTipRole else role)