class ExtendedCombo(QComboBox):
    def __init__(self, items=None, parent=None):
        super().__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())

        self.setCompleter(self.completer)

        self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setItems(self, items: list or set):
        self.items = list(items)

        model = QStandardItemModel()

        for i, student in enumerate(items):
            item = UserItem(student)
            model.setItem(i, 0, item)

        self.setModel(model)
        self.setModelColumn(0)

    def setModel(self, model):
        super(ExtendedCombo, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedCombo, self).setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)

    def currentItem(self):
        return self.items[self.currentIndex()]
Exemple #2
0
class SearchableComboBox(QComboBox):
    def __init__(self, parent=None):
        QComboBox.__init__(self, parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        self.completer = QCompleter(self)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)

        self.p_filter_model = QSortFilterProxyModel()
        self.p_filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.completer.popup())

        self.setCompleter(self.completer)

        self.lineEdit().textEdited.connect(
            self.p_filter_model.setFilterFixedString)

    def setModel(self, model):
        super().setModel(model)
        self.p_filter_model.setSourceModel(model)
        self.completer.setModel(self.p_filter_model)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.p_filter_model.setFilterKeyColumn(column)
        super().setModelColumn(column)

    def setTextIfCompleterIsClicked(self, text):
        if text:
            self.setCurrentIndex(self.findText(text))

    def setItems(self, items):
        self.clear()

        model = QStandardItemModel()

        for i, word in enumerate(items):
            item = QStandardItem(word)
            model.setItem(i, 0, item)

        self.setModel(model)
        self.setModelColumn(0)
class ExtendedCombo(QComboBox):
    def __init__(self):
        super().__init__()

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())

        self.setCompleter(self.completer)

        self.lineEdit().textEdited[str].connect(
            self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setModel(self, model):
        super(ExtendedCombo, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedCombo, self).setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
Exemple #4
0
class FilteredComboBox(QComboBox):
    def __init__(self, options, **kwargs):
        super().__init__()
        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        # self.dropEvent()
        self.completer = QCompleter(self)
        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setPopup(self.view())
        self.setCompleter(self.completer)
        the_style = "border-top-left-radius: 10px; border-bottom-left-radius: 10px; background-color: #f5f5f5;"
        self.lineEdit().setStyleSheet(the_style)
        if "height" in kwargs:
            self.setFixedHeight(kwargs["height"])
        else:
            self.setFixedHeight(37)

        self.lineEdit().textEdited.connect(
            self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)
        model = QStandardItemModel()
        for i, word in enumerate(options):
            item = QStandardItem(word)
            model.setItem(i, 0, item)
        self.setModel(model)
        self.setModelColumn(0)
        if "width" in kwargs:
            self.setFixedWidth(kwargs["width"])
        else:
            self.setFixedWidth(260)

        style = """
        QComboBox {
          border-radius: 10px;
        }

        QComboBox::drop-down:button{
            width: 25px;
            background-color: #f5f5f5;
            border-image: url(./resources/assets/images/drop_down.png);
            border-bottom-right-radius: 10px;
            border-top-right-radius: 10px;
        }

        QComboBox::drop-down:button:hover{
            background-color: #f5f5f5;
        }
        """
        self.setStyleSheet(style)

    def setModel(self, model):
        super(FilteredComboBox, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(FilteredComboBox, self).setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)

    def setMaximumWidth(self, p_int):
        self.setFixedWidth(p_int)
Exemple #5
0
class ExtendedLineEdit(QLineEdit):
    signal_send_movie = pyqtSignal(list)
    signal_search_movie = pyqtSignal(str)
    signal_request_movie_data = pyqtSignal(int)
    signal_set_loading = pyqtSignal(str, bool)

    DEBUG = False

    def __init__(self, parent=None):
        super(ExtendedLineEdit, self).__init__(parent)
        self.movies = []

        self.completer_lw = QListWidget()
        self.model = self.completer_lw.model()

        self.completer = QCompleter(self.model, self)
        self.completer.setPopup(self.completer_lw)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.completer.setCompletionRole(
            Qt.UserRole
        )  # Change role because default EditRole is paited to list somehow
        self.setCompleter(self.completer)

        self.textEdited.connect(self.text_edited)
        #self.completer.activated[QModelIndex].connect(self.on_completer_activated)
        #self.completer.activated[str].connect(self.on_completer_activated_str)
        self.completer_lw.itemClicked.connect(self.item_clicked)

        self.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress:
            if event.button() == Qt.LeftButton:
                self.completer.complete()
        return super(ExtendedLineEdit, self).eventFilter(obj, event)

    def setText(self, text: str) -> None:
        if self.DEBUG: print('setText', text, self.sender())
        super(ExtendedLineEdit, self).setText(text)
        if not isinstance(self.sender(), QCompleter) and text:
            self.text_edited(text)

    @pyqtSlot(list)
    def update_movies_list(self, result):
        if self.DEBUG: print('update_movies_list', result[0], len(result) - 1)
        type = result.pop(0)

        if type == 'db':
            self.movies = [x + [
                type,
            ] for x in result]
            self.completer_lw.clear()
            self.completer.complete()
        else:
            for item in result:
                self.movies.append(item + [
                    type,
                ])

        for item in result:
            cwidget = MyWidget()
            cwidget.label_movie_name.setText(item[1] if item[1] else item[2])
            cwidget.label_original_name.setText(item[2])
            cwidget.label_source.setText(type)
            cwidget.label_year.setText(str(item[3]))

            completer_myQListWidgetItem = QListWidgetItem(self.completer_lw)
            completer_myQListWidgetItem.setSizeHint(cwidget.sizeHint())
            completer_myQListWidgetItem.setData(Qt.UserRole, item[1])
            self.completer_lw.addItem(completer_myQListWidgetItem)
            self.completer_lw.setItemWidget(completer_myQListWidgetItem,
                                            cwidget)

        if self.hasFocus() and not self.completer_lw.isVisible() and len(
                self.movies) > 0:
            self.completer.complete()

    @pyqtSlot(str)
    def text_edited(self, text):
        if self.DEBUG: print('text_edited', text, self.sender())
        if text and isinstance(self.sender(), ExtendedLineEdit):
            self.signal_search_movie.emit(text)

    @pyqtSlot(str)
    def on_completer_activated_str(self, name: str):
        if self.DEBUG: print('on_completer_activated_str', name)

    @pyqtSlot(QModelIndex)
    def on_completer_activated(self, index: QModelIndex):
        if self.DEBUG: print('on_completer_activated', index.row())
        item = self.movies[index.row()]

        if len(item) > 13:
            self.signal_send_movie.emit(item[:13])
            self.signal_request_movie_data.emit(item[13])
        else:
            self.signal_send_movie.emit(item)

    @pyqtSlot(QListWidgetItem)
    def item_clicked(self, item: QListWidgetItem):
        if self.DEBUG: print('item_clicked', item, [i[1] for i in self.movies])
        index = self.completer_lw.indexFromItem(item)
        item = self.movies[index.row()]
        type = item[-1]

        if type == 'db':
            self.signal_send_movie.emit(item)
        else:
            self.signal_set_loading.emit('movie', True)

            if len(item) > 13:
                self.signal_send_movie.emit(item[:13])
                self.signal_request_movie_data.emit(item[13])
            else:
                self.signal_send_movie.emit(item)

    def reset(self):
        if self.DEBUG: print('reset')
        self.completer_lw.clear()
        self.clearFocus()
Exemple #6
0
	def init_toolbar(self):
		self.toolbar = QToolBar()
		self.toolbar.setFixedHeight(25)
		self.toolbar.setWindowTitle("Show") # text for the contextmenu
		#self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined?
		self.toolbar.setMovable(False)
		self.toolbar.setFloatable(False)
		#self.toolbar.setIconSize(QSize(20,20))
		self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		self.toolbar.setIconSize(QSize(20,20))

		spacer_start = QWidget() # aligns the first actions properly
		spacer_start.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_start)

		self.favourite_btn = misc.ToolbarButton(self.toolbar, 'Favorites')
		self.toolbar.addWidget(self.favourite_btn)
		self.favourite_btn.clicked.connect(self.favourite_display) #need lambda to pass extra args

		self.library_btn = misc.ToolbarButton(self.toolbar, 'Library')
		self.toolbar.addWidget(self.library_btn)
		self.library_btn.clicked.connect(self.catalog_display) #need lambda to pass extra args
		self.library_btn.selected = True

		self.toolbar.addSeparator()

		gallery_menu = QMenu()
		gallery_action = QToolButton()
		gallery_action.setText('Gallery ')
		gallery_action.setPopupMode(QToolButton.InstantPopup)
		gallery_action.setToolTip('Contains various gallery related features')
		gallery_action.setMenu(gallery_menu)
		add_gallery_icon = QIcon(app_constants.PLUS_PATH)
		gallery_action_add = QAction(add_gallery_icon, "Add single gallery...", self)
		gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit)
		gallery_action_add.setToolTip('Add a single gallery thoroughly')
		gallery_menu.addAction(gallery_action_add)
		add_more_action = QAction(add_gallery_icon, "Add galleries...", self)
		add_more_action.setStatusTip('Add galleries from different folders')
		add_more_action.triggered.connect(lambda: self.populate(True))
		gallery_menu.addAction(add_more_action)
		populate_action = QAction(add_gallery_icon, "Populate from directory/archive...", self)
		populate_action.setStatusTip('Populates the DB with galleries from a single folder or archive')
		populate_action.triggered.connect(self.populate)
		gallery_menu.addAction(populate_action)
		gallery_menu.addSeparator()
		metadata_action = QAction('Get metadata for all galleries', self)
		metadata_action.triggered.connect(self.get_metadata)
		gallery_menu.addAction(metadata_action)
		scan_galleries_action = QAction('Scan for new galleries', self)
		scan_galleries_action.triggered.connect(self.scan_for_new_galleries)
		scan_galleries_action.setStatusTip('Scan monitored folders for new galleries')
		gallery_menu.addAction(scan_galleries_action)
		gallery_action_random = gallery_menu.addAction("Open random gallery")
		gallery_action_random.triggered.connect(self.manga_list_view.open_random_gallery)
		self.toolbar.addWidget(gallery_action)


		misc_action = QToolButton()
		misc_action.setText('Tools ')
		misc_action_menu = QMenu()
		misc_action.setMenu(misc_action_menu)
		misc_action.setPopupMode(QToolButton.InstantPopup)
		misc_action.setToolTip("Contains misc. features")
		gallery_downloader = QAction("Gallery Downloader", misc_action_menu)
		gallery_downloader.triggered.connect(self.download_window.show)
		misc_action_menu.addAction(gallery_downloader)
		duplicate_check_simple = QAction("Simple Duplicate Finder", misc_action_menu)
		duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check())
		misc_action_menu.addAction(duplicate_check_simple)
		self.toolbar.addWidget(misc_action)

		spacer_middle = QWidget() # aligns buttons to the right
		spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
		self.toolbar.addWidget(spacer_middle)


		sort_action = QToolButton()
		sort_action.setIcon(QIcon(app_constants.SORT_PATH))
		sort_action.setMenu(misc.SortMenu(self.toolbar, self.manga_list_view))
		sort_action.setPopupMode(QToolButton.InstantPopup)
		self.toolbar.addWidget(sort_action)
		
		self.grid_toggle_g_icon = QIcon(app_constants.GRID_PATH)
		self.grid_toggle_l_icon = QIcon(app_constants.LIST_PATH)
		self.grid_toggle = QToolButton()
		if self.display.currentIndex() == self.m_l_view_index:
			self.grid_toggle.setIcon(self.grid_toggle_l_icon)
		else:
			self.grid_toggle.setIcon(self.grid_toggle_g_icon)
		self.grid_toggle.setObjectName('gridtoggle')
		self.grid_toggle.clicked.connect(self.toggle_view)
		self.toolbar.addWidget(self.grid_toggle)

		spacer_mid2 = QWidget()
		spacer_mid2.setFixedSize(QSize(5, 1))
		self.toolbar.addWidget(spacer_mid2)

		def set_search_case(b):
			app_constants.GALLERY_SEARCH_CASE = b
			settings.set(b, 'Application', 'gallery search case')
			settings.save()

		def set_search_strict(b):
			app_constants.GALLERY_SEARCH_STRICT = b
			settings.set(b, 'Application', 'gallery search strict')
			settings.save()

		self.search_bar = misc.LineEdit()
		search_options = self.search_bar.addAction(QIcon(app_constants.SEARCH_OPTIONS_PATH), QLineEdit.TrailingPosition)
		search_options_menu = QMenu(self)
		search_options.triggered.connect(lambda: search_options_menu.popup(QCursor.pos()))
		search_options.setMenu(search_options_menu)
		case_search_option = search_options_menu.addAction('Case Sensitive')
		case_search_option.setCheckable(True)
		case_search_option.setChecked(app_constants.GALLERY_SEARCH_CASE)
		case_search_option.toggled.connect(set_search_case)
		strict_search_option = search_options_menu.addAction('Match whole terms')
		strict_search_option.setCheckable(True)
		strict_search_option.setChecked(app_constants.GALLERY_SEARCH_STRICT)
		strict_search_option.toggled.connect(set_search_strict)
		self.search_bar.setObjectName('search_bar')
		self.search_timer = QTimer(self)
		self.search_timer.setSingleShot(True)
		self.search_timer.timeout.connect(lambda: self.search(self.search_bar.text()))
		self._search_cursor_pos = [0, 0]
		def set_cursor_pos(old, new):
			self._search_cursor_pos[0] = old
			self._search_cursor_pos[1] = new
		self.search_bar.cursorPositionChanged.connect(set_cursor_pos)

		if app_constants.SEARCH_AUTOCOMPLETE:
			completer = QCompleter(self)
			completer_view = misc.CompleterPopupView()
			completer.setPopup(completer_view)
			completer_view._setup()
			completer.setModel(self.manga_list_view.gallery_model)
			completer.setCaseSensitivity(Qt.CaseInsensitive)
			completer.setCompletionMode(QCompleter.PopupCompletion)
			completer.setCompletionRole(Qt.DisplayRole)
			completer.setCompletionColumn(app_constants.TITLE)
			completer.setFilterMode(Qt.MatchContains)
			self.search_bar.setCompleter(completer)
			self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text()))
		if not app_constants.SEARCH_ON_ENTER:
			self.search_bar.textEdited.connect(lambda: self.search_timer.start(800))
		self.search_bar.setPlaceholderText("Search title, artist, namespace & tags")
		self.search_bar.setMinimumWidth(150)
		self.search_bar.setMaximumWidth(500)
		self.search_bar.setFixedHeight(19)
		self.manga_list_view.sort_model.HISTORY_SEARCH_TERM.connect(lambda a: self.search_bar.setText(a))
		self.toolbar.addWidget(self.search_bar)

		def search_history(_, back=True): # clicked signal passes a bool
			sort_model =  self.manga_list_view.sort_model
			nav = sort_model.PREV if back else sort_model.NEXT
			history_term = sort_model.navigate_history(nav)
			if back:
				self.search_forward.setVisible(True)

		back = QShortcut(QKeySequence(QKeySequence.Back), self, lambda: search_history(None))
		forward = QShortcut(QKeySequence(QKeySequence.Forward), self, lambda: search_history(None, False))

		search_backbutton = QToolButton(self.toolbar)
		search_backbutton.setText(u'\u25C0')
		search_backbutton.setFixedWidth(15)
		search_backbutton.clicked.connect(search_history)
		self.search_backward = self.toolbar.addWidget(search_backbutton)
		self.search_backward.setVisible(False)
		search_forwardbutton = QToolButton(self.toolbar)
		search_forwardbutton.setText(u'\u25B6')
		search_forwardbutton.setFixedWidth(15)
		search_forwardbutton.clicked.connect(lambda: search_history(None, False))
		self.search_forward = self.toolbar.addWidget(search_forwardbutton)
		self.search_forward.setVisible(False)

		spacer_end = QWidget() # aligns settings action properly
		spacer_end.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_end)

		settings_act = QToolButton(self.toolbar)
		settings_act.setIcon(QIcon(app_constants.SETTINGS_PATH))
		settings_act.clicked.connect(self.settings)
		self.toolbar.addWidget(settings_act)

		spacer_end2 = QWidget() # aligns About action properly
		spacer_end2.setFixedSize(QSize(5, 1))
		self.toolbar.addWidget(spacer_end2)
		self.addToolBar(self.toolbar)
class DiscoveryPlugin:
    def __init__(self, _iface):
        # Save reference to the QGIS interface
        self.iface = _iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # Variables to facilitate delayed queries and database connection management
        self.icon_loading = ':plugins/_Discovery_sqlite/icons/loading.gif'
        self.db_timer = QTimer()
        self.line_edit_timer = QTimer()
        self.line_edit_timer.setSingleShot(True)
        self.line_edit_timer.timeout.connect(self.reset_line_edit_after_move)
        self.next_query_time = None
        self.last_query_time = time.time()
        self.db_conn = None
        self.search_delay = 0.5  # s
        self.query_sql = ''
        self.query_text = ''
        self.query_dict = {}
        self.db_idle_time = 60.0  # s

        self.search_results = []
        self.tool_bar = None
        self.search_line_edit = None
        self.completer = None

        self.marker = QgsVertexMarker(iface.mapCanvas())
        self.marker.setIconSize(15)
        self.marker.setPenWidth(2)
        self.marker.setColor(QColor(226, 27, 28))  #51,160,44))
        self.marker.setZValue(11)
        self.marker.setVisible(False)
        self.marker2 = QgsVertexMarker(iface.mapCanvas())
        self.marker2.setIconSize(16)
        self.marker2.setPenWidth(4)
        self.marker2.setColor(QColor(255, 255, 255, 200))
        self.marker2.setZValue(10)
        self.marker2.setVisible(False)

    def initGui(self):

        # Create a new toolbar
        self.tool_bar = self.iface.addToolBar(u'Панель поиска')
        self.tool_bar.setObjectName('Discovery_sqlite_Plugin')

        # Add search edit box
        self.search_line_edit = QgsFilterLineEdit()
        self.search_line_edit.setSelectOnFocus(True)
        self.search_line_edit.setShowSearchIcon(True)
        self.search_line_edit.setPlaceholderText(
            u'Поиск адреса или участка...')
        # self.search_line_edit.setMaximumWidth(768)
        self.tool_bar.addWidget(self.search_line_edit)

        # loading indicator
        self.load_movie = QMovie()
        self.label_load = QLabel()
        self.tool_bar.addWidget(self.label_load)

        # Set up the completer
        model = QStandardItemModel()
        self.completer = QCompleter([])  # Initialise with en empty list
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setMaxVisibleItems(30)
        self.completer.setModelSorting(
            QCompleter.UnsortedModel)  # Sorting done in PostGIS
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion
                                         )  # Show all fetched possibilities
        self.completer.setModel(model)
        tableView = QTableView()
        tableView.verticalHeader().setVisible(False)
        tableView.horizontalHeader().setVisible(False)
        tableView.setSelectionBehavior(QTableView.SelectRows)
        tableView.setShowGrid(False)
        # tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        tableView.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
        fontsize = QFontMetrics(
            tableView.verticalHeader().font()).height() + 2  #font size
        tableView.verticalHeader().setDefaultSectionSize(
            fontsize)  #font size 15
        tableView.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        tableView.horizontalHeader().setStretchLastSection(True)
        tableView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.completer.setCompletionColumn(0)
        self.completer.setPopup(tableView)

        self.completer.activated[QModelIndex].connect(self.on_result_selected)
        self.completer.highlighted[QModelIndex].connect(
            self.on_result_highlighted)
        self.search_line_edit.setCompleter(self.completer)

        # Connect any signals
        self.search_line_edit.textEdited.connect(self.on_search_text_changed)
        self.search_line_edit.returnPressed.connect(self.returnPressed)

        self.read_config()

        # Search results
        self.search_results = []

        # Set up a timer to periodically perform db queries as required
        self.db_timer.timeout.connect(self.schedule_search)

    def read_config(self):
        qstring = ''
        self.data = self.settings_path()
        try:
            for line in self.data[1:]:
                words = line.split(';')
                postgissearchcolumn = words[2].strip()
                postgistable = words[0].strip()
                geomcolumn = words[3].strip()
                layername = words[4].strip()
                isSelect = int(words[5].strip())

                connection = sqlite3.connect(os.path.join(self.dbfile.strip()))

                cur = connection.cursor()

                qstring = u'select {2} from {0} where length({1})>0 LIMIT 1'.format(
                    postgistable, postgissearchcolumn, geomcolumn)
                cur.execute(qstring)
                connection.close()
            self.make_enabled(True)  # assume the config is invalid first
        except Exception as E:
            print(E)
            self.make_enabled(False)

    # включить или выключить поисковую строку в зависимости от результата проверки настроек
    def make_enabled(self, enabled):
        self.search_line_edit.setEnabled(enabled)
        self.search_line_edit.setPlaceholderText(
            u"Поиск адреса или участка..."
            if enabled else u"Поиск отключен: проверьте конфигурацию")

    def settings_path(self):
        p = os.path.join(self.plugin_dir, 'layers.ini')
        f = codecs.open(p, 'r', encoding='cp1251')
        data = f.readlines()

        dbfileline = data[0]
        if dbfileline[:2] == u'\\\\':
            self.dbfile = dbfileline
        elif dbfileline[1] == u':':
            self.dbfile = dbfileline
        else:
            self.dbfile = os.path.join(self.plugin_dir, dbfileline)
        f.close()
        return data

    def unload(self):
        self.db_timer.stop()
        self.db_timer.timeout.disconnect(self.schedule_search)
        self.completer.highlighted[QModelIndex].disconnect(
            self.on_result_highlighted)
        self.completer.activated[QModelIndex].disconnect(
            self.on_result_selected)
        self.search_line_edit.textEdited.disconnect(
            self.on_search_text_changed)
        self.search_line_edit.returnPressed.disconnect(self.returnPressed)
        self.tool_bar.clear()  # Clear all actions
        self.iface.mainWindow().removeToolBar(self.tool_bar)

    def clear_suggestions(self):
        model = self.completer.model()
        model.clear()
        # model.setStringList([])

    def returnPressed(self):
        if self.completer.popup().isHidden():
            self.do_search(self.search_line_edit.text())

    # def setLoading(self, isLoading):
    #     if self.label_load is None:
    #         return
    #     if isLoading:
    #         load_movie = QMovie()
    #         load_movie.setFileName(self.icon_loading)
    #         self.label_load.setMovie(load_movie)
    #         load_movie.start()
    #     else:
    #         load_movie = QMovie()
    #         load_movie.stop()
    #         self.label_load.setMovie(load_movie)

    def schedule_search(self):

        if self.next_query_time is not None and self.next_query_time < time.time(
        ):
            self.next_query_time = None  # Prevent this query from being repeated
            self.last_query_time = time.time()
            self.do_search(self.search_line_edit.text())
            self.db_timer.stop()
            # self.setLoading(False)
            self.search_line_edit.setShowSpinner(False)
        else:
            # self.setLoading(True)
            self.search_line_edit.setShowSpinner(True)
            if time.time() > self.last_query_time + self.db_idle_time:
                self.db_conn = None

    # def on_search_text_changed(self, new_search_text):
    def on_search_text_changed(self, new_search_text):
        # self.setLoading(False)
        self.search_line_edit.setShowSpinner(False)
        if len(new_search_text) < 3:
            self.db_timer.stop()
            self.clear_suggestions()
            return
        self.db_timer.start(300)
        self.next_query_time = time.time() + self.search_delay

    def do_search(self, new_search_text):

        if len(new_search_text) < 3:
            self.clear_suggestions()
            return

        self.clear_suggestions()

        self.query_text = new_search_text

        self.search_results = []
        self.suggestions = []

        for index, line in enumerate(self.data[1:]):
            curline_layer = line
            words = curline_layer.split(';')
            searchcolumn = words[2].strip()  # поле со значением для поиска
            postgistable = words[0].strip()  # таблица
            geomcolumn = words[3].strip()  # поле с геометрией
            layername = words[4].strip(
            )  # имя слоя в легенде для соответствий и выделения
            isSelect = int(
                words[5].strip())  # выделять ли объект в слое layername
            descript = words[1].strip(
            )  # описание. Выводится в списке результатов

            query_text, query_dict = self.get_search_sql(
                new_search_text, searchcolumn, postgistable)

            query_sql = query_text
            query_dict = query_dict
            self.perform_search(query_sql, query_dict, descript, postgistable,
                                layername, isSelect, searchcolumn)

        # QStringList - просто одна строка в выводе
        # if len(self.suggestions) > 0:
        #     model = self.completer.model()
        #     model.setStringList(self.suggestions)
        #     print(model)
        #     self.completer.complete()

        if len(self.suggestions) > 0:
            # model = self.completer.model()
            model = QStandardItemModel()
            font = QFont()
            font.setItalic(True)
            font.setPointSize(7)
            # заполняем модель
            for i, line in enumerate(self.suggestions):
                #icon
                pixmap = QPixmap(':plugins/_Discovery_sqlite/icons/' +
                                 line[2] + '.png')
                pixmap = pixmap.scaledToHeight(10)
                pixmap = pixmap.scaledToWidth(10)
                # itemImage = QStandardItem()
                # itemImage.setData(pixmap, Qt.DecorationRole)
                # model.setItem(i, 0, itemImage)

                itemLayer = QStandardItem(u"{1}[{0}]".format(
                    line[1], u' ' * 50))
                itemLayer.setFont(font)
                itemValue = QStandardItem(line[0])
                itemValue.setData(pixmap, Qt.DecorationRole)
                model.setItem(i, 0, itemValue)
                model.setItem(i, 1, itemLayer)

            self.completer.setModel(model)
            self.completer.complete()

        else:
            model = self.completer.model()
            # self.suggestions.append(u"<Не найдено>")   # для QStringList
            # model.setStringList(self.suggestions)   # для QStringList
            model.setItem(
                0, 0, QStandardItem('<Не найдено>'))  # для QStandardItemModel
            self.completer.complete()

    def perform_search(self, query_sql, query_dict, descript, tablename,
                       layername, isSelect, searchcolumn):
        cur = self.get_db_cur()
        cur.execute(query_sql, query_dict)
        for row in cur.fetchall():
            geom, suggestion_text = row[0], row[1]
            self.search_results.append(geom)
            self.suggestions.append([
                suggestion_text, descript, tablename, layername, isSelect,
                searchcolumn
            ])
            # self.suggestions.append(suggestion_text)   # для QStringList

    def get_search_sql(self, search_text, search_column, table):

        wildcarded_search_string = ''
        for part in search_text.split():
            wildcarded_search_string += '%' + part  #.lower()
        wildcarded_search_string += '%'
        wildcarded_search_string = wildcarded_search_string
        query_dict = {'search_text': wildcarded_search_string}

        # wildcarded_search_string = wildcarded_search_string.encode('cp1251')
        query_text = u"SELECT WKT_GEOMETRY AS geom, {0} AS suggestion_string FROM {1} WHERE ({0}) LIKE '{2}' ORDER BY {0} LIMIT 1000".format(
            search_column, table, wildcarded_search_string)
        # query_text = query_text.decode('cp1251')
        return query_text, query_dict

    def on_result_selected(self, result_index):
        resultIndexRow = result_index.row()

        if len(self.search_results) < 1:
            self.search_line_edit.setPlaceholderText(u'')
            return
        # What to do when the user makes a selection
        geometry_text = self.search_results[resultIndexRow]
        location_geom = QgsGeometry.fromWkt(geometry_text)
        canvas = self.iface.mapCanvas()
        # dst_srid = canvas.mapRenderer().destinationCrs().authid()
        # Ensure the geometry from the DB is reprojected to the same SRID as the map canvas
        location_centroid = location_geom.centroid().asPoint()

        result_text = self.completer.completionModel().index(
            resultIndexRow, 0).data()

        if self.suggestions[resultIndexRow][2] in (
                u"adres_nd") and location_geom.type() == 0:  # point
            self.show_marker(location_centroid)
            self.iface.mapCanvas().setExtent(location_geom.boundingBox())
            self.iface.mapCanvas().zoomScale(1000)
            layer_build = self.find_layer(u"Здания")
            if layer_build != None:
                layer_build.selectByIds([])
                for feat in layer_build.getFeatures(
                        QgsFeatureRequest().setFilterRect(
                            QgsRectangle(self.iface.mapCanvas().extent()))):
                    if location_geom.intersects(feat.geometry()):
                        # self.show_marker_feature(feat.geometry())
                        self.iface.setActiveLayer(layer_build)
                        layer_build.selectByIds([feat.id()])
                        layer_build.triggerRepaint()
                        return

        else:  #not point
            layername = self.suggestions[resultIndexRow][3]
            isSelect = self.suggestions[resultIndexRow][4]
            searchcolumn = self.suggestions[resultIndexRow][5]

            box = location_geom.boundingBox()
            if box.height() > box.width():
                max = box.height()
            else:
                max = box.width()
            box.grow(max * 0.10)
            self.iface.mapCanvas().setExtent(box)

            if isSelect == 1:
                selLayer = self.find_layer(layername)
                if selLayer is not None:
                    for feat in selLayer.getFeatures(
                            QgsFeatureRequest().setFilterRect(box)):
                        # print(feat[searchcolumn], str(result_text).strip())
                        try:
                            if str(feat[searchcolumn]) == str(
                                    result_text).strip():
                                self.iface.setActiveLayer(selLayer)
                                selLayer.selectByIds([feat.id()])
                                selLayer.triggerRepaint()
                                break
                        except Exception as E:
                            print(E)
                            break

            self.show_marker_feature(location_geom)

        canvas.refresh()
        self.line_edit_timer.start(0)
        # self.db_timer.stop()

    def get_db_cur(self):
        # Create a new new connection if required
        if self.db_conn is None:
            self.db_conn = sqlite3.connect(os.path.join(self.dbfile.strip()))
        return self.db_conn.cursor()

    def on_result_highlighted(self, result_idx):
        self.line_edit_timer.start(0)

    def reset_line_edit_after_move(self):
        self.search_line_edit.setText(self.query_text)

    def find_layer(self, layer_name):
        for search_layer in self.iface.mapCanvas().layers():
            if search_layer.name() == layer_name:
                return search_layer
        return None

    def show_marker(self, point):
        for m in [self.marker, self.marker2]:
            m.setCenter(point)
            m.setOpacity(1.0)
            m.setVisible(True)
        QTimer.singleShot(4000, self.hide_marker)

    def hide_marker(self):
        opacity = self.marker.opacity()
        if opacity > 0.:
            # produce a fade out effect
            opacity -= 0.1
            self.marker.setOpacity(opacity)
            self.marker2.setOpacity(opacity)
            QTimer.singleShot(100, self.hide_marker)
        else:
            self.marker.setVisible(False)
            self.marker2.setVisible(False)

    def show_marker_feature(self, geom):
        if geom.type() == 2:  #poly
            self.r = QgsRubberBand(iface.mapCanvas(), True)
        elif geom.type() == 1:  #line
            self.r = QgsRubberBand(iface.mapCanvas(), False)
        self.r.setToGeometry(geom, None)
        self.r.setColor(QColor(255, 0, 0, 200))
        self.r.setFillColor(QColor(255, 0, 0, 50))
        self.r.setWidth(2)
        self.r.setZValue(9)

        QTimer.singleShot(4000, self.hide_marker_feature)

    def hide_marker_feature(self):
        opacity = self.r.opacity()
        if opacity > 0.:
            # produce a fade out effect
            opacity -= 0.1
            self.r.setOpacity(opacity)
            QTimer.singleShot(100, self.hide_marker_feature)
        else:
            iface.mapCanvas().scene().removeItem(self.r)
Exemple #8
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__()

        self.setGeometry(300, 300, 400, 300)

        fid = open('example.db', 'w')
        fid.close()

        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName('example.db')
        db.open()
        query = QSqlQuery(db)

        query.exec_('CREATE TABLE "airports" ("city" TEXT, "code" TEXT)')

        airports = [('Aberdeen, SD', 'ABR'), ('Abilene, TX', 'ABI'),
                    ('Adak Island, AK', 'ADK'), ('Akiachak, AK', 'KKI'),
                    ('Akiak, AK', 'AKI'), ('Akron/Canton, OH', 'CAK'),
                    ('Akuton, AK', 'KQA'), ('Alakanuk, AK', 'AUK'),
                    ('Alamogordo, NM', 'ALM'), ('Alamosa, CO', 'ALS'),
                    ('Albany, NY', 'ALB'), ('Albuquerque, NM', 'ABQ')]
        for item in airports:
            sql = 'INSERT INTO airports(city, code) VALUES(?, ?)'
            query.prepare(sql)
            query.addBindValue(item[0])
            query.addBindValue(item[1])
            query.exec_()

        query.exec_('SELECT * FROM airports')

        model = QSqlQueryModel()
        model.setQuery(query)

        self.cb = QComboBox(parent=self)
        self.cb.setModel(model)
        self.cb.setModelColumn(1)
        self.cb.setView(QTableView(self.cb))
        self.cb.setGeometry(50, 50, 250, 50)
        self.cb.currentIndexChanged.connect(self.indexer)

        self.label = QLabel(parent=self)
        self.label.setGeometry(20, 200, 250, 50)

        self.cb.view().setMinimumWidth(500)
        self.cb.setEditable(True)

        self.completer = QCompleter()
        self.completer.setCaseSensitivity(False)
        self.cb.setCompleter(self.completer)
        self.completer.setModel(model)
        self.completer.setCompletionColumn(1)
        self.completer.setPopup(QTableView())
        self.completer.popup().setMinimumWidth(500)
        self.completer.popup().setMinimumHeight(500)

        self.completer.activated.connect(self.activatedHandler)

    #@pyqtSlot(QObject)
    def activatedHandler(self, arg):
        pass

    def indexer(self, idx):
        self.label.setText('%d' % idx)