Exemplo n.º 1
0
    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(self.handle_link)
        self.attributesView.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        action = self.attributesView.pageAction(QWebPage.Copy)
        action.setShortcut(QKeySequence.Copy)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)
        self.project = None
        self.startwidth = self.width()
        self.expaned = False
        self.layerList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.expandButton.pressed.connect(self.change_expanded_state)
        self.navwidget.mousePressEvent = self._sink
        self.bottomWidget.mousePressEvent = self._sink
        self.navwidget.mouseReleaseEvent = self._sink
        self.bottomWidget.mouseReleaseEvent = self._sink
        self.navwidget.mouseMoveEvent = self._sink
        self.bottomWidget.mouseMoveEvent = self._sink
        self.deleteFeatureButton.pressed.connect(self.delete_feature)
        self.deleteFeatureButton.setCheckable(False)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)
Exemplo n.º 2
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)
    closewidget = pyqtSignal()

    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

    def selected(self, index):
        self._index = index
        self.itemselected.emit(index)

    def setmodel(self, model):
        self.listView.setModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def currentindex(self):
        return self._index

    def setcurrentindex(self, index):
        if index is None:
            index = QModelIndex()
        if isinstance(index, int):
            index = self.listView.model().index(index, 0)
        self.listView.setCurrentIndex(index)
Exemplo n.º 3
0
class ProjectsWidget(Ui_ListModules, QWidget):
    requestOpenProject = pyqtSignal(object)
    def __init__(self, parent = None):
        super(ProjectsWidget, self).__init__(parent)
        self.setupUi(self)
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.moduleList)
        self.moduleList.itemClicked.connect(self.openProject)

    def loadProjectList(self, projects):
        self.moduleList.clear()
        for project in projects:
            if not project.valid:
                roam.utils.warning("Project {} is invalid because {}".format(project.name, project.error))
                continue

            item = QListWidgetItem(self.moduleList, QListWidgetItem.UserType)
            item.setData(QListWidgetItem.UserType, project)
            item.setSizeHint(QSize(150, 150))
            
            projectwidget = ProjectWidget(self.moduleList)
            projectwidget.image = QPixmap(project.splash)
            projectwidget.name = project.name
            projectwidget.description = project.description
            projectwidget.version = project.version

            self.moduleList.addItem(item)
            self.moduleList.setItemWidget(item, projectwidget)
                              
    def openProject(self, item):
#        self.setDisabled(True)
        project = item.data(QListWidgetItem.UserType)
        self.selectedProject = project
        self.requestOpenProject.emit(project)
Exemplo n.º 4
0
class HelpPage(helppage_widget, helppage_base):
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.charm = FlickCharm()
        self.charm.activateOn(self.webView)
        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self.setsize()
        elif event.type() == QEvent.MouseButtonPress:
            self.close()
        return object.eventFilter(object, event)

    def setsize(self):
        width = self.parent().width() * 50 / 100
        self.resize(width, self.parent().height())
        self.move(self.parent().width() - self.width() -1, 1)

    def show(self):
        super(HelpPage, self).show()
        self.setsize()
        self.setFocus(Qt.PopupFocusReason)

    def setHelpPage(self, helppath):
        self.webView.load(QUrl.fromLocalFile(helppath))
Exemplo n.º 5
0
class ProjectsWidget(modules_widget, modules_base):
    requestOpenProject = pyqtSignal(object)
    def __init__(self, parent = None):
        super(ProjectsWidget, self).__init__(parent)
        self.setupUi(self)
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.moduleList)
        self.moduleList.itemClicked.connect(self.openProject)

    def loadProjectList(self, projects):
        self.moduleList.clear()
        for project in projects:
            if not project.valid:
                continue
            
            item = QListWidgetItem(self.moduleList, QListWidgetItem.UserType)
            item.setData(QListWidgetItem.UserType, project)
            item.setSizeHint(QSize(150, 150))
            
            projectwidget = ProjectWidget(self.moduleList)
            projectwidget.image = QPixmap(project.splash)
            projectwidget.name = project.name
            projectwidget.description = project.description
            projectwidget.version = project.version
            
            self.moduleList.addItem(item)
            self.moduleList.setItemWidget(item, projectwidget)
                              
    def openProject(self, item):
#        self.setDisabled(True)
        project = item.data(QListWidgetItem.UserType)
        self.selectedProject = project
        self.requestOpenProject.emit(project)
Exemplo n.º 6
0
class HelpPage(helppage_widget, helppage_base):
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.charm = FlickCharm()
        self.charm.activateOn(self.webView)
        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self.setsize()
        elif event.type() == QEvent.MouseButtonPress:
            self.close()
        return object.eventFilter(object, event)

    def setsize(self):
        width = self.parent().width() * 50 / 100
        self.resize(width, self.parent().height())
        self.move(self.parent().width() - self.width() - 1, 1)

    def show(self):
        super(HelpPage, self).show()
        self.setsize()
        self.setFocus(Qt.PopupFocusReason)

    def setHelpPage(self, helppath):
        self.webView.load(QUrl.fromLocalFile(helppath))
Exemplo n.º 7
0
 def __init__(self, parent=None):
     super(SyncWidget, self).__init__(parent)
     self.setupUi(self)
     self.syncrunning = False
     self.syncallButton.hide()
     self.flickcharm = FlickCharm()
     self.flickcharm.activateOn(self.scrollArea)
     self.flickcharm.activateOn(self.syncstatus)
Exemplo n.º 8
0
 def __init__(self, parent=None):
     super(ProjectsWidget, self).__init__(parent)
     self.setupUi(self)
     self.serverurl = None
     self.flickcharm = FlickCharm()
     self.flickcharm.activateOn(self.moduleList)
     self.moduleList.itemClicked.connect(self.openProject)
     self.projectitems = {}
     self.project_base = None
Exemplo n.º 9
0
    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)
Exemplo n.º 10
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)
    closewidget = pyqtSignal()
    savewidget = pyqtSignal()

    def __init__(self, parent=None, centeronparent=False, showsave=True):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.centeronparent = centeronparent
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)
        self.listView.setWordWrap(True)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

        self.saveButton.setVisible(showsave)

    def set_filter(self, text):
        self.filtermodel.setFilterRegExp(text + ".*")

    def selected(self, index):
        self._index = index
        self._index = self.filtermodel.mapToSource(index)
        self.itemselected.emit(self._index)

    def setmodel(self, model):
        self.filtermodel.setSourceModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def currentindex(self):
        return self._index

    def setcurrentindex(self, index):
        if index is None:
            index = QModelIndex()
        if isinstance(index, int):
            index = self.listView.model().index(index, 0)
        self.listView.setCurrentIndex(index)

    def show(self):
        super(BigList, self).show()

        if self.centeronparent:
            width = self.parent().width()
            height = self.parent().height()
            self.move(width / 4, 0)
            self.resize(QSize(width / 2, height))
Exemplo n.º 11
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)
    closewidget = pyqtSignal()
    savewidget = pyqtSignal()

    def __init__(self, parent=None, centeronparent=False, showsave=True):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.centeronparent = centeronparent
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)
        self.listView.setWordWrap(True)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

        self.saveButton.setVisible(showsave)

    def set_filter(self, text):
        self.filtermodel.setFilterRegExp(text + ".*")

    def selected(self, index):
        self._index = index
        self._index = self.filtermodel.mapToSource(index)
        self.itemselected.emit(self._index)

    def setmodel(self, model):
        self.filtermodel.setSourceModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def currentindex(self):
        return self._index

    def setcurrentindex(self, index):
        if index is None:
            index = QModelIndex()
        if isinstance(index, int):
            index = self.listView.model().index(index, 0)
        self.listView.setCurrentIndex(index)

    def show(self):
        super(BigList, self).show()

        if self.centeronparent:
            width = self.parent().width()
            height = self.parent().height()
            self.move(width / 4, 0)
            self.resize(QSize(width /2, height))
Exemplo n.º 12
0
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.charm = FlickCharm()
        self.charm.activateOn(self.webView)
        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
Exemplo n.º 13
0
    def __init__(self, parent=None):
        super(FeatureFormWidget, self).__init__(parent)
        self.setupUi(self)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"),
                                              "Delete")
        self.actionDelete.triggered.connect(self.delete_feature)

        label = '<b style="color:red">*</b> Required fields'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)

        titlespacer = QWidget()
        titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        toolbar.addWidget(titlespacer)
        self.titlellabel = QLabel(label)
        self.titlellabel.setProperty("headerlabel", True)
        self.titlelabelaction = toolbar.addWidget(self.titlellabel)

        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(40)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"),
                                              "Cancel")
        toolbar.addWidget(spacer2)
        self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save")
        self.actionSave.triggered.connect(self.save_feature)

        self.layout().setContentsMargins(0, 3, 0, 3)
        self.layout().insertWidget(0, toolbar)
        self.actiontoolbar = QToolBar()
        self.actiontoolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.actiontoolbar.addWidget(spacer)
        self.layout().insertWidget(1, self.actiontoolbar)

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        self.featureform = None
        self.values = {}
        self.config = {}
        self.feature = None
Exemplo n.º 14
0
    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)
Exemplo n.º 15
0
 def __init__(self, api, parent=None):
     super(SearchPlugin, self).__init__(parent)
     self.setupUi(self)
     self.api = api
     self.project = None
     self.dbpath = None
     self.flickcharm = FlickCharm()
     self.flickcharm.activateOn(self.resultsView)
     self.searchbox.textChanged.connect(self.search)
     self.searchbox.installEventFilter(self)
     self.resultsView.itemClicked.connect(self.jump_to)
     self.rebuildLabel.linkActivated.connect(self.rebuild_index)
     self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
     self.indexbuilder = None
     self.indexthread = None
 def __init__(self, parent = None):
     super(ProjectsWidget, self).__init__(parent)
     self.setupUi(self)
     self.flickcharm = FlickCharm()
     self.flickcharm.activateOn(self.moduleList)
     self.moduleList.itemClicked.connect(self.openProject)
     self.projectitems = {}
Exemplo n.º 17
0
    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(self.handle_link)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)
        self.project = None
        self.startwidth = self.width()
        self.expaned = False

        self.expandButton.pressed.connect(self.change_expanded_state)
        self.navwidget.mousePressEvent = self._sink
        self.bottomWidget.mousePressEvent = self._sink
        self.navwidget.mouseReleaseEvent = self._sink
        self.bottomWidget.mouseReleaseEvent = self._sink
        self.navwidget.mouseMoveEvent = self._sink
        self.bottomWidget.mouseMoveEvent = self._sink

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)
Exemplo n.º 18
0
    def __init__(self, canvas, bar, parent=None):
        super(DataEntryWidget, self).__init__(parent)
        self.setupUi(self)
        self.featureform = None
        self.project = None
        self.canvas = canvas
        self.bar = bar

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        toolbar = QToolBar()
        size = QSize(32, 32)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionSave.triggered.connect(self.accept)
        self.actionCancel.triggered.connect(functools.partial(self.reject, None))

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)
        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.actionSave)
        toolbar.addWidget(spacer2)
        toolbar.addAction(self.actionCancel)
        self.layout().insertWidget(2, toolbar)

        self.actionSave
class ProjectsWidget(Ui_ListModules, QWidget):
    requestOpenProject = pyqtSignal(object)

    def __init__(self, parent = None):
        super(ProjectsWidget, self).__init__(parent)
        self.setupUi(self)
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.moduleList)
        self.moduleList.itemClicked.connect(self.openProject)
        self.projectitems = {}

    def loadProjectList(self, projects):
        self.moduleList.clear()
        self.projectitems.clear()
        for project in projects:
            if not project.valid:
                roam.utils.warning("Project {} is invalid because {}".format(project.name, project.error))
                continue

            item = QListWidgetItem(self.moduleList, QListWidgetItem.UserType)
            item.setData(QListWidgetItem.UserType, project)
            item.setSizeHint(QSize(150, 150))
            
            projectwidget = ProjectWidget(project, self.moduleList)
            projectwidget.image = QPixmap(project.splash)
            projectwidget.name = project.name
            projectwidget.description = project.description
            projectwidget.version = project.version

            self.moduleList.addItem(item)
            self.moduleList.setItemWidget(item, projectwidget)
            self.projectitems[project] = projectwidget

    def openProject(self, item):
#        self.setDisabled(True)
        project = item.data(QListWidgetItem.UserType)
        self.selectedProject = project
        self.requestOpenProject.emit(project)
        self.set_open_project(project)

    def set_open_project(self, currentproject):
        for project, widget in self.projectitems.iteritems():
            if currentproject:
                showclose = currentproject == project
            else:
                showclose = False
            widget.show_close(showclose)
Exemplo n.º 20
0
def installflickcharm(widget):
    """
    Installs the flick charm on every widget on the form.
    """
    widget.charm = FlickCharm()
    for child in widget.findChildren(QWidget):
        widget.charm.activateOn(child)
    return widget
Exemplo n.º 21
0
    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(RoamEvents.openurl.emit)
        self.attributesView.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)
Exemplo n.º 22
0
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.charm = FlickCharm()
        self.charm.activateOn(self.webView)
        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
Exemplo n.º 23
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)
    closewidget = pyqtSignal()
    savewidget = pyqtSignal()

    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

    def set_filter(self, text):
        self.filtermodel.setFilterRegExp(text + ".*")

    def selected(self, index):
        self._index = index
        self._index = self.filtermodel.mapToSource(index)
        self.itemselected.emit(self._index)

    def setmodel(self, model):
        self.filtermodel.setSourceModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def currentindex(self):
        return self._index

    def setcurrentindex(self, index):
        if index is None:
            index = QModelIndex()
        if isinstance(index, int):
            index = self.listView.model().index(index, 0)
        self.listView.setCurrentIndex(index)
Exemplo n.º 24
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)
    closewidget = pyqtSignal()
    savewidget = pyqtSignal()

    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

    def set_filter(self, text):
        self.filtermodel.setFilterRegExp(text + ".*")

    def selected(self, index):
        self._index = index
        self._index = self.filtermodel.mapToSource(index)
        self.itemselected.emit(self._index)

    def setmodel(self, model):
        self.filtermodel.setSourceModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def currentindex(self):
        return self._index

    def setcurrentindex(self, index):
        if index is None:
            index = QModelIndex()
        if isinstance(index, int):
            index = self.listView.model().index(index, 0)
        self.listView.setCurrentIndex(index)
Exemplo n.º 25
0
 def __init__(self, parent):
     super(InfoDock, self).__init__(parent)
     self.setupUi(self)
     self.forms = {}
     self.charm = FlickCharm()
     self.charm.activateOn(self.attributesView)
     self.layerList.currentRowChanged.connect(self.layerIndexChanged)
     self.attributesView.linkClicked.connect(openimage)
     self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
     self.grabGesture(Qt.SwipeGesture)
     self.setAttribute(Qt.WA_AcceptTouchEvents)
     self.editButton.pressed.connect(self.openform)
     self.parent().installEventFilter(self)
Exemplo n.º 26
0
    def __init__(self, canvas, parent=None):
        super(DataEntryWidget, self).__init__(parent)
        self.setupUi(self)
        self.featureform = None
        self.feature = None
        self.fields = None
        self.project = None
        self.canvas = canvas

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionSave.triggered.connect(self.accept)
        self.actionCancel.triggered.connect(
            functools.partial(self.formrejected, None))
        self.actionDelete.triggered.connect(self.deletefeature)

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        toolbar.addAction(self.actionDelete)
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)
        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.actionCancel)
        toolbar.addWidget(spacer2)
        toolbar.addAction(self.actionSave)

        self.data_entry_page.layout().insertWidget(0, toolbar)
Exemplo n.º 27
0
    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.selected)
        self.saveButton.pressed.connect(self.savewidget.emit)
        self.closebutton.pressed.connect(self.closewidget.emit)
        self._index = None
        self.search.textEdited.connect(self.set_filter)
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.listView.setModel(self.filtermodel)

        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)
Exemplo n.º 28
0
class BigList(Ui_BigList, QWidget):
    itemselected = pyqtSignal(QModelIndex)

    def __init__(self, parent=None):
        super(BigList, self).__init__(parent)
        self.setupUi(self)
        self.listView.clicked.connect(self.itemselected)
        self.charm = FlickCharm()
        self.charm.activateOn(self.listView)

    def setmodel(self, model):
        self.listView.setModel(model)

    def setlabel(self, fieldname):
        self.fieldnameLabel.setText(fieldname)

    def show(self):
        super(BigList, self).show()

        width = self.parent().width()
        height = self.parent().height()
        self.move(width / 4, 0)
        self.resize(QSize(width / 2, height))
Exemplo n.º 29
0
 def __init__(self, api, parent=None):
     super(SearchPlugin, self).__init__(parent)
     self.setupUi(self)
     self.api = api
     self.project = None
     self.dbpath = None
     self.flickcharm = FlickCharm()
     self.flickcharm.activateOn(self.resultsView)
     self.searchbox.textChanged.connect(self.search)
     self.searchbox.installEventFilter(self)
     self.resultsView.itemClicked.connect(self.jump_to)
     self.rebuildLabel.linkActivated.connect(self.rebuild_index)
     self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
     self.indexbuilder = None
     self.indexthread = None
Exemplo n.º 30
0
    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(RoamEvents.openurl.emit)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)
Exemplo n.º 31
0
    def __init__(self, parent=None):
        super(FeatureFormWidget, self).__init__(parent)
        self.setupUi(self)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"), "Delete")
        self.actionDelete.triggered.connect(self.delete_feature)

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)

        titlespacer = QWidget()
        titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        toolbar.addWidget(titlespacer)
        self.titlellabel = QLabel(label)
        self.titlellabel.setProperty("headerlabel", True)
        self.titlelabelaction = toolbar.addWidget(self.titlellabel)

        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"), "Cancel")
        toolbar.addWidget(spacer2)
        self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save")
        self.actionSave.triggered.connect(self.save_feature)

        self.layout().insertWidget(0, toolbar)

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        self.featureform = None
        self.values = {}
        self.config = {}
        self.feature = None
Exemplo n.º 32
0
    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(self.handle_link)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        action = self.attributesView.pageAction(QWebPage.Copy)
        action.setShortcut(QKeySequence.Copy)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)
        self.project = None
        self.startwidth = self.width()
        self.expaned = False
        self.layerList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.expandAction = QAction(QIcon(":/icons/expand"), "Expand Panel", self)
        self.expandAction.triggered.connect(self.change_expanded_state)

        self.navigateAction = QAction(QIcon(":/icons/navigate"), "Navigate To..", self)
        self.navigateAction.triggered.connect(self._navigate_to_selection)

        self.moreActionsButton.pressed.connect(self._show_more_actions)
        self.navwidget.mousePressEvent = self._sink
        self.bottomWidget.mousePressEvent = self._sink
        self.navwidget.mouseReleaseEvent = self._sink
        self.bottomWidget.mouseReleaseEvent = self._sink
        self.navwidget.mouseMoveEvent = self._sink
        self.bottomWidget.mouseMoveEvent = self._sink
        self.deleteFeatureButton.pressed.connect(self.delete_feature)
        self.deleteFeatureButton.setCheckable(False)

        self.nextButton.pressed.connect(self.pagenext)
        self.prevButton.pressed.connect(self.pageback)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)
Exemplo n.º 33
0
class InfoDock(infodock_widget, QWidget):
    featureupdated = pyqtSignal(object, object, list)
    resultscleared = pyqtSignal()

    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(RoamEvents.openurl.emit)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)
        self.project = None
        self.startwidth = self.width()
        self.expaned = False

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)

    def mouseDoubleClickEvent(self, QMouseEvent):
        if self.expaned:
            self._collapse()
        else:
            self._expand()

    def _expand(self):
        self.resize(self.parent().width() - 10, self.parent().height())
        self.move(10, 0)
        self.expaned = True

    def _collapse(self):
        self.resize(self.startwidth, self.parent().height())
        self.move(self.parent().width() - self.startwidth, 0)
        self.expaned = False

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self._collapse()

        return super(InfoDock, self).eventFilter(object, event)

    def close(self):
        RoamEvents.selectioncleared.emit()
        super(InfoDock, self).close()

    def event(self, event):
        if event.type() == QEvent.Gesture:
            gesture = event.gesture(Qt.SwipeGesture)
            if gesture:
                self.pagenext()
        return QWidget.event(self, event)

    @property
    def selection(self):
        item = self.layerList.item(self.layerList.currentRow())
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        return cursor

    def openform(self):
        cursor = self.selection
        RoamEvents.load_feature_form(cursor.form, cursor.feature, True)

    def editgeom(self):
        cursor = self.selection
        RoamEvents.editgeometry.emit(cursor.form, cursor.feature)

    def pageback(self):
        cursor = self.selection
        cursor.back()
        self.update(cursor)

    def pagenext(self):
        cursor = self.selection
        cursor.next()
        self.update(cursor)

    def layerIndexChanged(self, index):
        item = self.layerList.item(index)
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        self.update(cursor)

    def setResults(self, results, forms, project):
        lastrow = self.layerList.currentRow()
        if lastrow == -1:
            lastrow = 0

        self.clearResults()
        self.forms = forms
        self.project = project

        for layer, features in results.iteritems():
            if features:
                self._addResult(layer, features)

        self.layerList.setCurrentRow(lastrow)
        self.layerList.setMinimumWidth(self.layerList.sizeHintForColumn(0) + 20)
        self.layerList.setMinimumHeight(self.layerList.sizeHintForRow(0) + 20)
        self.navwidget.show()

    def show(self):
        if self.layerList.count() > 0:
            super(InfoDock, self).show()
        else:
            self.hide()

    def _addResult(self, layer, features):
        layername = layer.name()
        forms = self.forms.get(layername, [])
        if not forms:
            item = QListWidgetItem(QIcon(), layername, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features))
            return

        for form in forms:
            selectname = self.project.selectlayer_name(form.layername)
            print selectname
            if selectname == layername:
                itemtext = "{} \n ({})".format(layername, form.label)
            else:
                itemtext = selectname
            icon = QIcon(form.icon)
            item = QListWidgetItem(icon, itemtext, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features, form))

    def refreshcurrent(self):
        self.update(self.selection)

    def update(self, cursor):
        if cursor is None:
            return

        try:
            feature = cursor.feature
        except NoFeature as ex:
            utils.warning(ex)
            return


        form = cursor.form
        layer = cursor.layer

        clear_image_cache()

        info1, results = self.generate_info("info1", self.project, layer, feature.id(), feature)
        info2, _= self.generate_info("info2", self.project, layer, feature.id(), feature, lastresults=results[0])

        if form:
            name = "{}".format(layer.name(), form.label)
        else:
            name = layer.name()

        info = dict(TITLE=name,
                    INFO1=info1,
                    INFO2=info2)

        html = updateTemplate(info, template)

        self.countlabel.setText(str(cursor))
        self.attributesView.setHtml(html, templates.baseurl)
        tools = self.project.layer_tools(layer)
        hasform = not form is None
        editattributes = 'edit_attributes' in tools and hasform
        editgeom = 'edit_geom' in tools and hasform
        self.editButton.setVisible(editattributes)
        self.editGeomButton.setVisible(editgeom)
        self.featureupdated.emit(layer, feature, cursor.features)


    def generate_info(self, infoblock, project, layer, mapkey, feature, lastresults=None):

        info_template = Template("""
        <div class="panel panel-default">
          <div class="panel-heading text-left">
            <h2 class="panel-title" style="font-size:24px">${HEADER}</h2>
          </div>
          <div class="panel-body" style="padding:0px">
            <table class="table table-condensed">
                <col style="width: 35%;"/>
                <col style="width: 65%;"/>
            ${ROWS}
            </table>
            </div>
        </div>
        """)

        infoblockdef = project.info_query(infoblock, layer.name())
        isinfo1 = infoblock == "info1"
        if isinfo1:
            header = infoblockdef.get('caption', "Record")
        else:
            header = infoblockdef.get('caption', "Related Record")

        if not infoblockdef:
            if isinfo1:
                infoblockdef = {}
                infoblockdef['type'] = 'feature'
            else:
                return None, []

        results = []
        error = None
        if infoblockdef['type'] == 'sql':
            try:
                queryresults = self.results_from_query(infoblockdef, layer, feature, mapkey, lastresults=lastresults)
                if isinfo1 and not queryresults:
                    # If there is no results from the query and we are a info 1 block we grab from the feature.
                    results.append(self.results_from_feature(feature))
                else:
                    results = queryresults
            except database.DatabaseException as ex:
                if not isinfo1:
                    error = "<b> Error: {} <b>".format(ex.msg)
                else:
                    results.append(self.results_from_feature(feature))

        elif infoblockdef['type'] == 'feature':
            results.append(self.results_from_feature(feature))
        else:
            return None, []

        blocks = []
        for count, result in enumerate(results, start=1):
            if not isinfo1:
                newheader = "{} {} of {}".format(header,count, len(results))
            else:
                newheader = header
            fields = result.keys()
            attributes = result.values()
            rows = generate_rows(fields, attributes)
            blocks.append(updateTemplate(dict(ROWS=rows,
                                              HEADER=newheader), info_template))
        if error:
            return error, []

        return '<br>'.join(blocks), results

    def results_from_feature(self, feature):
        return values_from_feature(feature)

    def results_from_query(self, infoblockdef, layer, feature, mapkey, lastresults=None):
        def get_key():
            try:
                keycolumn = infoblockdef['mapping']['mapkey']
                if keycolumn == 'from_info1':
                    if 'mapkey' in lastresults:
                        return lastresults['mapkey']
                    else:
                        return []
                else:
                    return feature[keycolumn]
            except KeyError:
                return mapkey

        def get_layer():
            connection = infoblockdef['connection']
            if isinstance(connection, dict):
                return layer_by_name(connection['layer'])
            elif connection == "from_layer":
                return layer
            else:
                raise NotImplementedError("{} is not a supported connection type".format(connection))

        if not lastresults:
            lastresults = {}

        sql = infoblockdef['query']
        layer = get_layer()

        db = database.Database.fromLayer(layer)
        mapkey = get_key()
        results = db.query(sql, mapkey=mapkey)
        return list(results)

    def clearResults(self):
        self.layerList.clear()
        self.attributesView.setHtml('')
        self.editButton.setVisible(False)
        self.navwidget.hide()
Exemplo n.º 34
0
class SyncWidget(sync_widget, sync_base):
    syncqueue = []
    def __init__(self, parent=None):
        super(SyncWidget, self).__init__(parent)
        self.setupUi(self)
        self.syncrunning = False
        self.syncallButton.hide()
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.synctree)
        self.flickcharm.activateOn(self.syncstatus)

    def loadprojects(self, projects):
        root = self.synctree.invisibleRootItem()
        for project in projects:
            print project
            providers = list(project.syncprovders())
            print providers
            if not providers:
                continue

            projectitem = QTreeWidgetItem(root)
            projectitem.setText(0, project.name)
            projectitem.setIcon(0, QIcon(project.splash))
            for provider in providers:
                provideritem = QTreeWidgetItem(projectitem)
                provideritem.setText(0, provider.name)
                button = QPushButton()
                button.pressed.connect(partial(self.run, button, provider))
                button.setText(provider.name)
                self.synctree.setItemWidget(provideritem,0, button)

        self.synctree.expandAll()

    def updatestatus(self, message):
        self.syncstatus.append(message)
        self.syncstatus.ensureCursorVisible()

    def updatewitherror(self, message):
        self.updatestatus('<b style="color:red">Error in sync: {}</b>'.format(message))

    def updatecomplete(self):
        self.updatestatus('<b style="color:darkgreen">Sync complete</b>')

    def runnext(self):
        try:
            provider = SyncWidget.syncqueue.pop(0)
            provider.syncComplete.connect(self.updatecomplete)
            provider.syncComplete.connect(self.runnext)
            provider.syncMessage.connect(self.updatestatus)
            provider.syncError.connect(self.updatewitherror)
            provider.start()
        except IndexError:
            # If we get here we have run out of providers to run
            return

    def disconnect(self, provider):
        try:
            provider.syncComplete.disconnect()
            provider.syncMessage.disconnect()
            provider.syncStarted.disconnect()
            provider.syncError.disconnect()
        except TypeError:
            pass

    def syncfinished(self, button, provider):
        self.disconnect(provider)
        button.setText(provider.name)
        button.setEnabled(True)
        self.syncrunning = False

    def syncstarted(self, button, provider):
        self.updatestatus('<b style="font-size:large">Sync started for {}</h3>'.format(provider.name))
        button.setText('Running')
        button.setEnabled(False)
        self.syncrunning = True

    def run(self, button, provider):
        provider.syncStarted.connect(partial(self.syncstarted, button, provider))
        provider.syncFinished.connect(partial(self.syncfinished, button, provider))

        SyncWidget.syncqueue.append(provider)
        if self.syncrunning:
            button.setText("Pending")
        else:
            self.runnext()
Exemplo n.º 35
0
class InfoDock(infodock_widget, QWidget):
    featureupdated = pyqtSignal(object, object, list)
    resultscleared = pyqtSignal()

    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(RoamEvents.openurl.emit)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self.resize(self.width(), self.parent().height())
            self.move(self.parent().width() - self.width(), 0)

        return super(InfoDock, self).eventFilter(object, event)

    def close(self):
        RoamEvents.selectioncleared.emit()
        super(InfoDock, self).close()

    def event(self, event):
        if event.type() == QEvent.Gesture:
            gesture = event.gesture(Qt.SwipeGesture)
            if gesture:
                self.pagenext()
        return QWidget.event(self, event)

    @property
    def selection(self):
        item = self.layerList.item(self.layerList.currentRow())
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        return cursor

    def openform(self):
        cursor = self.selection
        RoamEvents.openfeatureform.emit(cursor.form, cursor.feature, True)

    def editgeom(self):
        cursor = self.selection
        RoamEvents.editgeometry.emit(cursor.form, cursor.feature)

    def pageback(self):
        cursor = self.selection
        cursor.back()
        self.update(cursor)

    def pagenext(self):
        cursor = self.selection
        cursor.next()
        self.update(cursor)

    def layerIndexChanged(self, index):
        item = self.layerList.item(index)
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        self.update(cursor)

    def setResults(self, results, forms):
        lastrow = self.layerList.currentRow()
        if lastrow == -1:
            lastrow = 0

        self.clearResults()
        self.forms = forms

        for layer, features in results.iteritems():
            if features:
                self._addResult(layer, features)

        self.layerList.setCurrentRow(lastrow)
        self.layerList.setMinimumWidth(self.layerList.sizeHintForColumn(0) + 20)
        self.navwidget.show()

    def show(self):
        if self.layerList.count() > 0:
            super(InfoDock, self).show()
        else:
            self.hide()

    def _addResult(self, layer, features):
        layername = layer.name()
        forms = self.forms.get(layername, [])
        if not forms:
            item = QListWidgetItem(QIcon(), layername, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features))
            return

        for form in forms:
            itemtext = "{} \n ({})".format(layername, form.label)
            icon = QIcon(form.icon)
            item = QListWidgetItem(icon, itemtext, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features, form))

    def refreshcurrent(self):
        self.update(self.selection)

    def update(self, cursor):
        if cursor is None:
            return

        try:
            feature = cursor.feature
        except NoFeature as ex:
            utils.warning(ex)
            return

        fields = [field.name() for field in feature.fields()]
        data = OrderedDict()

        items = []
        for field, value in zip(fields, feature.attributes()):
            data[field] = value
            item = u"<tr><th>{0}</th> <td>${{{0}}}</td></tr>".format(field)
            items.append(item)
        rowtemple = Template(''.join(items))
        rowshtml = updateTemplate(data, rowtemple)

        form = cursor.form
        layer = cursor.layer
        if form:
            name = "{}".format(layer.name(), form.label)
        else:
            name = layer.name()

        info = dict(TITLE=name,
                    ROWS=rowshtml)

        html = updateTemplate(info, template)

        self.countlabel.setText(str(cursor))
        self.attributesView.setHtml(html, templates.baseurl)
        self.editButton.setVisible(not form is None)
        self.featureupdated.emit(layer, feature, cursor.features)

    def clearResults(self):
        self.layerList.clear()
        self.attributesView.setHtml('')
        self.editButton.setVisible(False)
        self.navwidget.hide()
Exemplo n.º 36
0
class FeatureFormWidget(Ui_Form, QWidget):
    # Raise the cancel event, takes a reason and a level
    canceled = pyqtSignal(str, int)
    featuresaved = pyqtSignal()
    featuredeleted = pyqtSignal()

    def __init__(self, parent=None):
        super(FeatureFormWidget, self).__init__(parent)
        self.setupUi(self)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"),
                                              "Delete")
        self.actionDelete.triggered.connect(self.delete_feature)

        label = '<b style="color:red">*</b> Required fields'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)

        titlespacer = QWidget()
        titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        toolbar.addWidget(titlespacer)
        self.titlellabel = QLabel(label)
        self.titlellabel.setProperty("headerlabel", True)
        self.titlelabelaction = toolbar.addWidget(self.titlellabel)

        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(40)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"),
                                              "Cancel")
        toolbar.addWidget(spacer2)
        self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save")
        self.actionSave.triggered.connect(self.save_feature)

        self.layout().setContentsMargins(0, 3, 0, 3)
        self.layout().insertWidget(0, toolbar)
        self.actiontoolbar = QToolBar()
        self.actiontoolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.actiontoolbar.addWidget(spacer)
        self.layout().insertWidget(1, self.actiontoolbar)

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        self.featureform = None
        self.values = {}
        self.config = {}
        self.feature = None

    def set_featureform(self, featureform):
        """
        Note: There can only be one feature form.  If you need to show another one make a new FeatureFormWidget
        """
        self.featureform = featureform
        self.titlellabel.setText(self.featureform.windowTitle())
        self.featureform.formvalidation.connect(self._update_validation)
        self.featureform.helprequest.connect(
            functools.partial(RoamEvents.helprequest.emit, self))
        self.featureform.showlargewidget.connect(RoamEvents.show_widget.emit)
        self.featureform.enablesave.connect(self.actionSave.setEnabled)
        self.featureform.enablesave.connect(self.actionSave.setVisible)
        self.featureform.rejected.connect(self.canceled.emit)
        self.featureform.accepted.connect(self.featuresaved)

        actions = self.featureform.form_actions()
        if actions:
            for action in actions:
                self.actiontoolbar.addAction(action)
        else:
            self.actiontoolbar.hide()

        self.featureform.setContentsMargins(0, 0, 0, 0)
        self.featureformarea.layout().addWidget(self.featureform)

    def delete_feature(self):
        try:
            msg = self.featureform.deletemessage
        except AttributeError:
            msg = 'Do you really want to delete this feature?'

        box = DeleteFeatureDialog(msg)

        if not box.exec_():
            return

        try:
            self.featureform.delete()
        except featureform.DeleteFeatureException as ex:
            RoamEvents.raisemessage(*ex.error)

        self.featureform.featuredeleted(self.feature)
        self.featuredeleted.emit()

    def feature_saved(self):
        self.featuresaved.emit()
        RoamEvents.featuresaved.emit()

    def save_feature(self):
        try:
            self.featureform.save()
        except featureform.MissingValuesException as ex:
            RoamEvents.raisemessage(*ex.error)
            return
        except featureform.FeatureSaveException as ex:
            RoamEvents.raisemessage(*ex.error)

        self.feature_saved()

    def set_config(self, config):
        self.config = config
        editmode = config['editmode']
        allowsave = config.get('allowsave', True)
        self.feature = config.get('feature', None)
        tools = config.get('tools', [])
        candelete = True
        if tools:
            candelete = "delete" in tools
        self.featureform.feature = self.feature
        self.featureform.editingmode = editmode
        self.actionDelete.setVisible(editmode and candelete)
        self.actionSave.setEnabled(allowsave)

    def _update_validation(self, passed):
        # Show the error if there is missing fields
        self.missingfieldaction.setVisible(not passed)

    def bind_values(self, values):
        self.values = values
        self.featureform.bindvalues(values)

    def after_load(self):
        self.featureform.loaded()

    def before_load(self):
        self.featureform.load(self.config['feature'], self.config['layers'],
                              self.values)
Exemplo n.º 37
0
class SearchPlugin(widget, base, Page):
    title = "Search"
    icon = resolve("search.svg")

    def __init__(self, api, parent=None):
        super(SearchPlugin, self).__init__(parent)
        self.setupUi(self)
        self.api = api
        self.project = None
        self.dbpath = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.resultsView)
        self.searchbox.textChanged.connect(self.search)
        self.searchbox.installEventFilter(self)
        self.resultsView.itemClicked.connect(self.jump_to)
        self.rebuildLabel.linkActivated.connect(self.rebuild_index)
        self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
        self.indexbuilder = None
        self.indexthread = None

    def fuzzy_changed(self, state):
        self.search(self.searchbox.text())

    def index_built(self, dbpath, timing):
        self.dbpath = dbpath
        self.resultsView.clear()
        self.searchbox.setEnabled(True)
        print "Index built in: {} seconds".format(timing)

    def eventFilter(self, object, event):
        if event.type() == QEvent.FocusIn:
            RoamEvents.openkeyboard.emit()
        return False

    @property
    def db(self):
        db = sqlite3.connect(self.dbpath)
        db.create_function("rank", 1, make_rank_func((1., .1, 0, 0)))
        return db

    def project_loaded(self, project):
        self.project = project
        self.build_index(project)

    def rebuild_index(self):
        self.build_index(self.project)

    def build_index(self, project):
        self.searchbox.setEnabled(False)
        self.resultsView.setEnabled(False)
        self.resultsView.addItem(
            "Just let me build the search index first....")

        validformat, settings = valid_search_settings(project.settings)
        if not validformat:
            RoamEvents.raisemessage("Searching",
                                    "Invalid search config.",
                                    level=1)
            self.searchbox.hide()
            self.resultsView.clear()
            self.resultsView.addItem("Invalid search config found")
            return

        self.indexthread = QThread()
        self.indexbuilder = IndexBuilder(project.folder, settings)
        self.indexbuilder.moveToThread(self.indexthread)

        QgsMapLayerRegistry.instance().removeAll.connect(self.indexthread.quit)

        self.indexbuilder.indexBuilt.connect(self.index_built)
        self.indexbuilder.finished.connect(self.indexthread.quit)
        self.indexthread.started.connect(self.indexbuilder.build_index)
        self.indexthread.finished.connect(self.indexbuilder.quit)

        self.indexthread.start()

    def search(self, text):
        db = self.db
        c = db.cursor()
        self.resultsView.clear()
        self.resultsView.setEnabled(False)
        if not text:
            return

        if self.fuzzyCheck.isChecked():
            search = "* ".join(text.split()) + "*"
        else:
            search = text
        query = c.execute(
            """SELECT layer, featureid, snippet(search, '[',']') as snippet
                            FROM search
                            JOIN featureinfo on search.docid = featureinfo.id
                            WHERE search match '{}' LIMIT 100""".format(
                search)).fetchall()
        for layer, featureid, snippet in query:
            item = QListWidgetItem()
            text = "{}\n {}".format(layer, snippet.replace('\n', ' '))
            item.setText(text)
            item.setData(Qt.UserRole, (layer, featureid, snippet))
            self.resultsView.addItem(item)

        self.resultsView.setEnabled(True)

        if self.resultsView.count() == 0:
            self.resultsView.addItem("No Results")
            self.resultsView.setEnabled(False)
        db.close()

    def jump_to(self, item):
        data = item.data(32)
        if not data:
            return
        layername, fid = data[0], data[1]
        layer = roam.api.utils.layer_by_name(layername)
        feature = layer.getFeatures(QgsFeatureRequest(fid)).next()
        box = feature.geometry().boundingBox()
        xmin, xmax, ymin, ymax = box.xMinimum(), box.xMaximum(), box.yMinimum(
        ), box.yMaximum()
        xmin -= 5
        xmax += 5
        ymin -= 5
        ymax += 5
        box = QgsRectangle(xmin, ymin, xmax, ymax)
        self.api.mainwindow.canvas.setExtent(box)
        self.api.mainwindow.canvas.refresh()
        self.api.mainwindow.showmap()
        RoamEvents.selectionchanged.emit({layer: [feature]})
Exemplo n.º 38
0
class InfoDock(infodock_widget, QWidget):
    featureupdated = pyqtSignal(object, object, list)
    resultscleared = pyqtSignal()

    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(RoamEvents.openurl.emit)
        self.attributesView.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self.resize(self.width(), self.parent().height())
            self.move(self.parent().width() - self.width(), 0)

        return super(InfoDock, self).eventFilter(object, event)

    def close(self):
        RoamEvents.selectioncleared.emit()
        super(InfoDock, self).close()

    def event(self, event):
        if event.type() == QEvent.Gesture:
            gesture = event.gesture(Qt.SwipeGesture)
            if gesture:
                self.pagenext()
        return QWidget.event(self, event)

    @property
    def selection(self):
        item = self.layerList.item(self.layerList.currentRow())
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        return cursor

    def openform(self):
        cursor = self.selection
        RoamEvents.openfeatureform.emit(cursor.form, cursor.feature, True)

    def editgeom(self):
        cursor = self.selection
        RoamEvents.editgeometry.emit(cursor.form, cursor.feature)

    def pageback(self):
        cursor = self.selection
        cursor.back()
        self.update(cursor)

    def pagenext(self):
        cursor = self.selection
        cursor.next()
        self.update(cursor)

    def layerIndexChanged(self, index):
        item = self.layerList.item(index)
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        self.update(cursor)

    def setResults(self, results, forms):
        lastrow = self.layerList.currentRow()
        if lastrow == -1:
            lastrow = 0

        self.clearResults()
        self.forms = forms

        for layer, features in results.iteritems():
            if features:
                self._addResult(layer, features)

        self.layerList.setCurrentRow(lastrow)
        self.layerList.setMinimumWidth(
            self.layerList.sizeHintForColumn(0) + 20)
        self.navwidget.show()

    def show(self):
        if self.layerList.count() > 0:
            super(InfoDock, self).show()
        else:
            self.hide()

    def _addResult(self, layer, features):
        layername = layer.name()
        forms = self.forms.get(layername, [])
        if not forms:
            item = QListWidgetItem(QIcon(), layername, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features))
            return

        for form in forms:
            itemtext = "{} \n ({})".format(layername, form.label)
            icon = QIcon(form.icon)
            item = QListWidgetItem(icon, itemtext, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features, form))

    def refreshcurrent(self):
        self.update(self.selection)

    def update(self, cursor):
        if cursor is None:
            return

        try:
            feature = cursor.feature
        except NoFeature as ex:
            utils.warning(ex)
            return

        fields = [field.name() for field in feature.fields()]
        data = OrderedDict()

        items = []
        for field, value in zip(fields, feature.attributes()):
            data[field] = value
            item = u"<tr><th>{0}</th> <td>${{{0}}}</td></tr>".format(field)
            items.append(item)
        rowtemple = Template(''.join(items))
        rowshtml = updateTemplate(data, rowtemple)

        form = cursor.form
        layer = cursor.layer
        if form:
            name = "{}".format(layer.name(), form.label)
        else:
            name = layer.name()

        info = dict(TITLE=name, ROWS=rowshtml)

        html = updateTemplate(info, template)

        self.countlabel.setText(str(cursor))
        self.attributesView.setHtml(html, templates.baseurl)
        self.editButton.setVisible(not form is None)
        self.editGeomButton.setVisible(not form is None)
        self.featureupdated.emit(layer, feature, cursor.features)

    def clearResults(self):
        self.layerList.clear()
        self.attributesView.setHtml('')
        self.editButton.setVisible(False)
        self.navwidget.hide()
Exemplo n.º 39
0
class SyncWidget(Ui_Form, QWidget):
    syncqueue = []
    def __init__(self, parent=None):
        super(SyncWidget, self).__init__(parent)
        self.setupUi(self)
        self.syncrunning = False
        self.syncallButton.hide()
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.synctree)
        self.flickcharm.activateOn(self.syncstatus)

    def loadprojects(self, projects):
        root = self.synctree.invisibleRootItem()
        for project in projects:
            providers = list(project.syncprovders())
            if not providers:
                continue

            projectitem = QTreeWidgetItem(root)
            projectitem.setText(0, project.name)
            projectitem.setIcon(0, QIcon(project.splash))
            for provider in providers:
                provideritem = QTreeWidgetItem(projectitem)
                provideritem.setText(0, provider.name)
                button = QPushButton()
                button.pressed.connect(partial(self.run, button, provider))
                button.setText(provider.name)
                self.synctree.setItemWidget(provideritem,0, button)

        self.synctree.expandAll()

    def updatestatus(self, message):
        self.syncstatus.append(message)
        self.syncstatus.ensureCursorVisible()

    def updatewitherror(self, message):
        self.updatestatus('<b style="color:red">Error in sync: {}</b>'.format(message))
        self.updatestatus('')

    def updatecomplete(self):
        self.updatestatus('<b style="color:darkgreen">Sync complete</b>')
        self.updatestatus('')

    def runnext(self):
        try:
            provider = SyncWidget.syncqueue.pop(0)
            provider.syncComplete.connect(self.updatecomplete)
            provider.syncComplete.connect(self.runnext)
            provider.syncMessage.connect(self.updatestatus)
            provider.syncError.connect(self.updatewitherror)
            provider.start()
        except IndexError:
            # If we get here we have run out of providers to run
            return

    def disconnect(self, provider):
        try:
            provider.syncComplete.disconnect()
            provider.syncMessage.disconnect()
            provider.syncStarted.disconnect()
            provider.syncError.disconnect()
        except TypeError:
            pass

    def syncfinished(self, button, provider):
        self.disconnect(provider)
        button.setText(provider.name)
        button.setEnabled(True)
        self.syncrunning = False

    def syncstarted(self, button, provider):
        self.updatestatus('<b style="font-size:large">Sync started for {}</h3>'.format(provider.name))
        button.setText('Running')
        button.setEnabled(False)
        self.syncrunning = True

    def run(self, button, provider):
        provider.syncStarted.connect(partial(self.syncstarted, button, provider))
        provider.syncFinished.connect(partial(self.syncfinished, button, provider))

        SyncWidget.syncqueue.append(provider)
        if self.syncrunning:
            button.setText("Pending")
        else:
            self.runnext()
Exemplo n.º 40
0
class DataEntryWidget(dataentry_widget, dataentry_base):
    """
    """
    accepted = pyqtSignal()
    rejected = pyqtSignal(str, int)
    finished = pyqtSignal()
    featuresaved = pyqtSignal()
    featuredeleted = pyqtSignal(object, object)
    failedsave = pyqtSignal(list)
    helprequest = pyqtSignal(str)
    openimage = pyqtSignal(object)

    def __init__(self, canvas, parent=None):
        super(DataEntryWidget, self).__init__(parent)
        self.setupUi(self)
        self.featureform = None
        self.feature = None
        self.fields = None
        self.project = None
        self.canvas = canvas

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionSave.triggered.connect(self.accept)
        self.actionCancel.triggered.connect(
            functools.partial(self.formrejected, None))
        self.actionDelete.triggered.connect(self.deletefeature)

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        toolbar.addAction(self.actionDelete)
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)
        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.actionCancel)
        toolbar.addWidget(spacer2)
        toolbar.addAction(self.actionSave)

        self.data_entry_page.layout().insertWidget(0, toolbar)

    def deletefeature(self):
        try:
            msg = self.featureform.deletemessage
        except AttributeError:
            msg = 'Do you really want to delete this feature?'
        box = DeleteFeatureDialog(msg, QApplication.activeWindow())

        if not box.exec_():
            return

        featureid = self.feature.id()
        try:
            userdeleted = self.featureform.deletefeature()

            if not userdeleted:
                # If the user didn't add there own feature delete logic
                # we will just do it for them.
                layer = self.featureform.form.QGISLayer
                layer.startEditing()
                layer.deleteFeature(featureid)
                saved = layer.commitChanges()
                if not saved:
                    raise featureform.DeleteFeatureException(
                        layer.commitErrors())

        except featureform.DeleteFeatureException as ex:
            self.failedsave.emit([ex.message])
            map(error, ex.message)
            return

        self.featureform.featuredeleted(self.feature)
        self.featuredeleted.emit(self.featureform.form.QGISLayer, featureid)

    def accept(self):
        fields = [w['field'] for w in self.featureform.formconfig['widgets']]

        def updatefeautrefields(feature):
            for key, value in values.iteritems():
                try:
                    if key in fields:
                        feature[key] = field_or_null(value)
                    else:
                        feature[key] = value
                except KeyError:
                    continue
            return feature

        def field_or_null(field):
            if field == '' or field is None or isinstance(
                    field, QPyNullVariant):
                return QPyNullVariant(str)
            return field

        if not self.featureform.allpassing:
            RoamEvents.raisemessage("Missing fields",
                                    "Some fields are still required.",
                                    QgsMessageBar.WARNING,
                                    duration=2)
            return

        if not self.featureform:
            return

        if not self.featureform.accept():
            return

        layer = self.featureform.form.QGISLayer
        before = QgsFeature(self.feature)
        before.setFields(self.fields, initAttributes=False)

        values, savedvalues = self.featureform.getvalues()

        after = QgsFeature(self.feature)
        after.setFields(self.fields, initAttributes=False)
        after = updatefeautrefields(after)

        layer.startEditing()
        if after.id() > 0:
            if self.project.historyenabled(layer):
                # Mark the old one as history
                before['status'] = 'H'
                after['status'] = 'C'
                after['dateedited'] = QDateTime.currentDateTime()
                after['editedby'] = getpass.getuser()
                layer.addFeature(after)
                layer.updateFeature(before)
            else:
                layer.updateFeature(after)
        else:
            layer.addFeature(after)
            featureform.savevalues(layer, savedvalues)

        saved = layer.commitChanges()

        if not saved:
            self.failedsave.emit(layer.commitErrors())
            map(error, layer.commitErrors())
        else:
            self.featureform.featuresaved(after, values)
            self.featuresaved.emit()

        self.accepted.emit()
        self.featureform = None

    def formrejected(self,
                     message=None,
                     level=featureform.RejectedException.WARNING):
        self.clear()
        self.rejected.emit(message, level)

    def formvalidation(self, passed):
        self.missingfieldaction.setVisible(not passed)

    def setlargewidget(self, widgettype, lastvalue, callback, config):
        def cleanup():
            self.stackedWidget.setCurrentIndex(0)
            self.clearcurrentwidget(self.fullscreenwidget)
            del self.largewidgetwrapper

        widget = widgettype.createwidget()
        self.largewidgetwrapper = widgettype.for_widget(widget,
                                                        None,
                                                        None,
                                                        None,
                                                        None,
                                                        map=self.canvas)
        self.largewidgetwrapper.finished.connect(callback)
        self.largewidgetwrapper.finished.connect(cleanup)
        self.largewidgetwrapper.cancel.connect(cleanup)

        self.clearcurrentwidget(self.fullscreenwidget)
        self.fullscreenwidget.layout().insertWidget(0, widget)
        self.stackedWidget.setCurrentIndex(1)

        self.largewidgetwrapper.initWidget(widget)
        self.largewidgetwrapper.config = config
        self.largewidgetwrapper.setvalue(lastvalue)

    def setwidget(self, widget):
        self.clearcurrentwidget(self.scrollAreaWidgetContents)
        self.scrollAreaWidgetContents.layout().insertWidget(0, widget)
        self.stackedWidget.setCurrentIndex(0)

    def clear(self):
        self.featureform = None
        self.clearcurrentwidget(self.fullscreenwidget)
        self.clearcurrentwidget(self.scrollAreaWidgetContents)

    def clearcurrentwidget(self, parent):
        item = parent.layout().itemAt(0)
        if item and item.widget():
            widget = item.widget()
            widget.setParent(None)
            widget.deleteLater()

    def openform(self, form, feature, project, editmode):
        """
        Opens a form for the given feature.
        """

        roam.qgisfunctions.capturegeometry = feature.geometry()

        defaultvalues = {}
        layer = form.QGISLayer
        if not editmode:
            defaultwidgets = form.widgetswithdefaults()
            defaultvalues = defaults.default_values(defaultwidgets, feature,
                                                    layer)
            defaultvalues.update(featureform.loadsavedvalues(layer))

        self.actionDelete.setVisible(editmode)

        for field, value in defaultvalues.iteritems():
            feature[field] = value

        self.formvalidation(passed=True)
        self.feature = feature
        # Hold a reference to the fields because QGIS will let the
        # go out of scope and we get crashes. Yay!
        self.fields = self.feature.fields()
        self.featureform = form.create_featureform(feature,
                                                   defaultvalues,
                                                   canvas=self.canvas)
        self.featureform.editingmode = editmode
        self.featureform.rejected.connect(self.formrejected)
        self.featureform.enablesave.connect(self.actionSave.setEnabled)

        # Call the pre loading events for the form
        layers = QgsMapLayerRegistry.instance().mapLayers()

        self.project = project
        fields = [field.name().lower() for field in self.fields]
        attributes = feature.attributes()

        if layer.dataProvider().name() == 'spatialite':
            pkindexes = layer.dataProvider().pkAttributeIndexes()
            for index in pkindexes:
                del fields[index]
                del attributes[index]

        values = CaseInsensitiveDict(zip(fields, attributes))

        try:
            self.featureform.load(feature, layers, values)
        except featureform.RejectedException as rejected:
            self.formrejected(rejected.message, rejected.level)
            return

        self.featureform.formvalidation.connect(self.formvalidation)
        self.featureform.helprequest.connect(self.helprequest.emit)
        self.featureform.bindvalues(values)
        self.featureform.showlargewidget.connect(self.setlargewidget)

        self.actionSave.setVisible(True)
        self.setwidget(self.featureform)

        self.featureform.loaded()

        RoamEvents.featureformloaded.emit(form, feature, project, editmode)
Exemplo n.º 41
0
class DataEntryWidget(dataentry_widget, dataentry_base):
    """
    """
    accepted = pyqtSignal()
    rejected = pyqtSignal(str, int)
    finished = pyqtSignal()
    featuresaved = pyqtSignal()
    featuredeleted = pyqtSignal(object, object)
    failedsave = pyqtSignal(list)
    helprequest = pyqtSignal(str)
    openimage = pyqtSignal(object)

    def __init__(self, canvas, parent=None):
        super(DataEntryWidget, self).__init__(parent)
        self.setupUi(self)
        self.featureform = None
        self.feature = None
        self.fields = None
        self.project = None
        self.canvas = canvas

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionSave.triggered.connect(self.accept)
        self.actionCancel.triggered.connect(functools.partial(self.formrejected, None))
        self.actionDelete.triggered.connect(self.deletefeature)

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        toolbar.addAction(self.actionDelete)
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)
        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.actionCancel)
        toolbar.addWidget(spacer2)
        toolbar.addAction(self.actionSave)

        self.data_entry_page.layout().insertWidget(0, toolbar)

    def deletefeature(self):
        try:
            msg = self.featureform.deletemessage
        except AttributeError:
            msg = 'Do you really want to delete this feature?'
        box = DeleteFeatureDialog(msg, QApplication.activeWindow())

        if not box.exec_():
            return

        featureid = self.feature.id()
        try:
            userdeleted = self.featureform.deletefeature()

            if not userdeleted:
                # If the user didn't add there own feature delete logic
                # we will just do it for them.
                layer = self.featureform.form.QGISLayer
                layer.startEditing()
                layer.deleteFeature(featureid)
                saved = layer.commitChanges()
                if not saved:
                    raise featureform.DeleteFeatureException(layer.commitErrors())

        except featureform.DeleteFeatureException as ex:
            self.failedsave.emit([ex.message])
            map(error, ex.message)
            return

        self.featureform.featuredeleted(self.feature)
        self.featuredeleted.emit(self.featureform.form.QGISLayer, featureid)

    def accept(self):
        fields = [w['field'] for w in self.featureform.formconfig['widgets']]

        def updatefeautrefields(feature):
            for key, value in values.iteritems():
                try:
                    if key in fields:
                        feature[key] = field_or_null(value)
                    else:
                        feature[key] = value
                except KeyError:
                    continue
            return feature

        def field_or_null(field):
            if field == '' or field is None or isinstance(field, QPyNullVariant):
                return QPyNullVariant(str)
            return field

        if not self.featureform.allpassing:
            RoamEvents.raisemessage("Missing fields", "Some fields are still required.",
                                     QgsMessageBar.WARNING, duration=2)
            return

        if not self.featureform:
            return

        if not self.featureform.accept():
            return

        layer = self.featureform.form.QGISLayer
        before = QgsFeature(self.feature)
        before.setFields(self.fields, initAttributes=False)

        values, savedvalues = self.featureform.getvalues()

        after = QgsFeature(self.feature)
        after.setFields(self.fields, initAttributes=False)
        after = updatefeautrefields(after)

        layer.startEditing()
        if after.id() > 0:
            if self.project.historyenabled(layer):
                # Mark the old one as history
                before['status'] = 'H'
                after['status'] = 'C'
                after['dateedited'] = QDateTime.currentDateTime()
                after['editedby'] = getpass.getuser()
                layer.addFeature(after)
                layer.updateFeature(before)
            else:
                layer.updateFeature(after)
        else:
            layer.addFeature(after)
            featureform.savevalues(layer, savedvalues)

        saved = layer.commitChanges()

        if not saved:
            self.failedsave.emit(layer.commitErrors())
            map(error, layer.commitErrors())
        else:
            self.featureform.featuresaved(after, values)
            self.featuresaved.emit()

        self.accepted.emit()
        self.featureform = None

    def formrejected(self, message=None, level=featureform.RejectedException.WARNING):
        self.clear()
        self.rejected.emit(message, level)

    def formvalidation(self, passed):
        self.missingfieldaction.setVisible(not passed)

    def setlargewidget(self, widgettype, lastvalue, callback, config):
        def cleanup():
            self.stackedWidget.setCurrentIndex(0)
            self.clearcurrentwidget(self.fullscreenwidget)
            del self.largewidgetwrapper

        widget = widgettype.createwidget()
        self.largewidgetwrapper = widgettype.for_widget(widget, None, None, None, None, map=self.canvas)
        self.largewidgetwrapper.finished.connect(callback)
        self.largewidgetwrapper.finished.connect(cleanup)
        self.largewidgetwrapper.cancel.connect(cleanup)

        self.clearcurrentwidget(self.fullscreenwidget)
        self.fullscreenwidget.layout().insertWidget(0, widget)
        self.stackedWidget.setCurrentIndex(1)

        self.largewidgetwrapper.initWidget(widget)
        self.largewidgetwrapper.config = config
        self.largewidgetwrapper.setvalue(lastvalue)

    def setwidget(self, widget):
        self.clearcurrentwidget(self.scrollAreaWidgetContents)
        self.scrollAreaWidgetContents.layout().insertWidget(0, widget)
        self.stackedWidget.setCurrentIndex(0)

    def clear(self):
        self.featureform = None
        self.clearcurrentwidget(self.fullscreenwidget)
        self.clearcurrentwidget(self.scrollAreaWidgetContents)

    def clearcurrentwidget(self, parent):
        item = parent.layout().itemAt(0)
        if item and item.widget():
            widget = item.widget()
            widget.setParent(None)
            widget.deleteLater()

    def openform(self, form, feature, project, editmode):
        """
        Opens a form for the given feature.
        """

        roam.qgisfunctions.capturegeometry = feature.geometry()

        defaultvalues = {}
        layer = form.QGISLayer
        if not editmode:
            defaultwidgets = form.widgetswithdefaults()
            defaultvalues = defaults.default_values(defaultwidgets, feature, layer)
            defaultvalues.update(featureform.loadsavedvalues(layer))

        self.actionDelete.setVisible(editmode)

        for field, value in defaultvalues.iteritems():
            feature[field] = value

        self.formvalidation(passed=True)
        self.feature = feature
        # Hold a reference to the fields because QGIS will let the
        # go out of scope and we get crashes. Yay!
        self.fields = self.feature.fields()
        self.featureform = form.create_featureform(feature, defaultvalues, canvas=self.canvas)
        self.featureform.editingmode = editmode
        self.featureform.rejected.connect(self.formrejected)
        self.featureform.enablesave.connect(self.actionSave.setEnabled)

        # Call the pre loading events for the form
        layers = QgsMapLayerRegistry.instance().mapLayers()

        self.project = project
        fields = [field.name().lower() for field in self.fields]
        attributes = feature.attributes()

        if layer.dataProvider().name() == 'spatialite':
            pkindexes = layer.dataProvider().pkAttributeIndexes()
            for index in pkindexes:
                del fields[index]
                del attributes[index]

        values = CaseInsensitiveDict(zip(fields, attributes))

        try:
            self.featureform.load(feature, layers, values)
        except featureform.RejectedException as rejected:
            self.formrejected(rejected.message, rejected.level)
            return

        self.featureform.formvalidation.connect(self.formvalidation)
        self.featureform.helprequest.connect(self.helprequest.emit)
        self.featureform.bindvalues(values)
        self.featureform.showlargewidget.connect(self.setlargewidget)

        self.actionSave.setVisible(True)
        self.setwidget(self.featureform)

        self.featureform.loaded()

        RoamEvents.featureformloaded.emit(form, feature, project, editmode)
Exemplo n.º 42
0
class DataEntryWidget(dataentry_widget, dataentry_base):
    """
    """
    accepted = pyqtSignal()
    rejected = pyqtSignal(str)
    finished = pyqtSignal()
    featuresaved = pyqtSignal()
    failedsave = pyqtSignal(list)
    helprequest = pyqtSignal(str)

    def __init__(self, canvas, bar, parent=None):
        super(DataEntryWidget, self).__init__(parent)
        self.setupUi(self)
        self.featureform = None
        self.project = None
        self.canvas = canvas
        self.bar = bar

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        toolbar = QToolBar()
        size = QSize(32, 32)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionSave.triggered.connect(self.accept)
        self.actionCancel.triggered.connect(functools.partial(self.reject, None))

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)
        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        toolbar.addAction(self.actionSave)
        toolbar.addWidget(spacer2)
        toolbar.addAction(self.actionCancel)
        self.layout().insertWidget(2, toolbar)

        self.actionSave

    def accept(self):
        if not self.featureform.allpassing:
            self.bar.pushMessage("Missing fields", "Some fields are still required.",
                                 QgsMessageBar.WARNING, duration=2)
            return

        if not self.featureform:
            return

        if not self.featureform.accept():
            return

        layer = self.featureform.form.QGISLayer
        before, after, savedvalues = self.featureform.unbind()

        layer.startEditing()
        if after.id() > 0:
            if self.project.historyenabled(layer):
                # Mark the old one as history
                before['status'] = 'H'
                after['status'] = 'C'
                after['dateedited'] = QDateTime.currentDateTime()
                after['editedby'] = getpass.getuser()
                layer.addFeature(after)
                layer.updateFeature(before)
            else:
                layer.updateFeature(after)
        else:
            layer.addFeature(after)
            featureform.savevalues(layer, savedvalues)
        saved = layer.commitChanges()

        if not saved:
            self.failedsave.emit(layer.commitErrors())
            map(error, layer.commitErrors())
        else:
            self.featuresaved.emit()

        self.accepted.emit()
        self.finished.emit()
        self.featureform = None

    def reject(self, message):
        # Tell the form it is rejected
        if self.featureform:
            self.featureform.reject(message)

    def formrejected(self, message=None):
        self.clearcurrentwidget()
        self.rejected.emit(message)
        self.finished.emit()
        self.featureform = None

    def formvalidation(self, passed):
        self.missingfieldaction.setVisible(not passed)

    def showwidget(self, widget):
        self.actionSave.setVisible(False)
        self.setwidget(widget)

    def setwidget(self, widget):
        self.clearcurrentwidget()
        self.scrollAreaWidgetContents.layout().insertWidget(0, widget)

    def clear(self):
        self.featureform = None
        self.clearcurrentwidget()

    def clearcurrentwidget(self):
        item = self.scrollAreaWidgetContents.layout().itemAt(0)
        if item and item.widget():
            widget = item.widget()
            widget.deleteLater()

    def continueload(self):
        self.featureform.showwidget.disconnect()
        self.featureform.loadform.disconnect()

        self.featureform.formvalidation.connect(self.formvalidation)
        self.featureform.helprequest.connect(self.helprequest.emit)
        self.featureform.bind()

        self.actionSave.setVisible(True)
        self.setwidget(self.featureform.widget)

        self.featureform.loaded()

    def openform(self, form, feature, project):
        """
        Opens a form for the given feature.

        This method is connected using signals rather then a normal top down method.
        If the loadform signal is emitted from the FeatureForm
        the data entry widget will continue to bind and load the form.  If rejected is emitted
        the form will be rejected and the message will be shown to the user.

        This allows for pre form load checks that allow the form to show pre main form widgets
        using showwidget.
        """

        defaults = {}
        editing = feature.id() > 0
        if not editing:
            defaults = getdefaults(form.widgetswithdefaults(), feature, form.QGISLayer, self.canvas)

        for field, value in defaults.iteritems():
            feature[field] = value

        self.formvalidation(passed=True)
        self.feature = feature
        self.featureform = form.create_featureform(feature, defaults)
        self.featureform.showwidget.connect(self.showwidget)
        self.featureform.loadform.connect(self.continueload)
        self.featureform.rejected.connect(self.formrejected)

        # Call the pre loading evnts for the form
        layers = iter(QgsMapLayerRegistry.instance().mapLayers())

        self.project = project
        self.featureform.load(feature, layers, editing)
Exemplo n.º 43
0
class SearchPlugin(widget, base, Page):
    title = "Search"
    icon = resolve("search.svg")

    def __init__(self, api, parent=None):
        super(SearchPlugin, self).__init__(parent)
        self.setupUi(self)
        self.api = api
        self.project = None
        self.dbpath = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.resultsView)
        self.searchbox.textChanged.connect(self.search)
        self.searchbox.installEventFilter(self)
        self.clearButton.pressed.connect(self.searchbox.clear)
        self.resultsView.itemClicked.connect(self.jump_to)
        self.rebuildLabel.linkActivated.connect(self.rebuild_index)
        self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
        self.indexbuilder = None
        self.indexthread = None

    def fuzzy_changed(self, state):
        self.search(self.searchbox.text())

    def index_built(self, dbpath, timing):
        self.dbpath = dbpath
        self.resultsView.clear()
        self.searchbox.setEnabled(True)
        print "Index built in: {} seconds".format(timing)

    def eventFilter(self, object, event):
        if event.type() == QEvent.FocusIn:
            RoamEvents.openkeyboard.emit()
        return False

    @property
    def db(self):
        db = sqlite3.connect(self.dbpath)
        db.create_function("rank", 1, make_rank_func((1., .1, 0, 0)))
        return db

    def project_loaded(self, project):
        self.project = project
        self.build_index(project)

    def rebuild_index(self):
        self.build_index(self.project)

    def build_index(self, project):
        self.searchbox.setEnabled(False)
        self.resultsView.setEnabled(False)
        self.resultsView.addItem("building search index...")

        validformat, settings = valid_search_settings(project.settings)
        if not validformat:
            RoamEvents.raisemessage("Searching", "Invalid search config.", level=1)
            self.searchbox.hide()
            self.resultsView.clear()
            self.resultsView.addItem("Invalid search config found")
            return

        self.indexthread = QThread()
        path = os.path.join(os.environ['APPDATA'], "roam", project.name)

        roam.utils.info("Search index path: {0}".format(path))

        if not os.path.exists(path):
            os.makedirs(path)

        self.indexbuilder = IndexBuilder(path, settings)
        self.indexbuilder.moveToThread(self.indexthread)

        QgsMapLayerRegistry.instance().removeAll.connect(self.indexthread.quit)

        self.indexbuilder.indexBuilt.connect(self.index_built)
        self.indexbuilder.finished.connect(self.indexthread.quit)
        self.indexthread.started.connect(self.indexbuilder.build_index)
        self.indexthread.finished.connect(self.indexbuilder.quit)

        self.indexthread.start()

    def search(self, text):
        db = self.db
        c = db.cursor()
        self.resultsView.clear()
        self.resultsView.setEnabled(False)
        if not text:
            return

        if self.fuzzyCheck.isChecked():
            search = "* ".join(text.split()) + "*"
        else:
            search = text
        query = c.execute("""SELECT layer, featureid, snippet(search, '[',']') as snippet
                            FROM search
                            JOIN featureinfo on search.docid = featureinfo.id
                            WHERE search match '{}' LIMIT 100""".format(search)).fetchall()
        for layer, featureid, snippet in query:
            item = QListWidgetItem()
            text = "{}\n {}".format(layer, snippet.replace('\n', ' '))
            item.setText(text)
            item.setData(Qt.UserRole, (layer, featureid, snippet))
            self.resultsView.addItem(item)

        self.resultsView.setEnabled(True)

        if self.resultsView.count() == 0:
            self.resultsView.addItem("No Results")
            self.resultsView.setEnabled(False)
        db.close()

    def jump_to(self, item):
        data = item.data(32)
        if not data:
            return
        layername, fid = data[0], data[1]
        layer = roam.api.utils.layer_by_name(layername)
        feature = layer.getFeatures(QgsFeatureRequest(fid)).next()
        box = feature.geometry().boundingBox()
        xmin, xmax, ymin, ymax = box.xMinimum(), box.xMaximum(), box.yMinimum(), box.yMaximum()
        xmin -= 5
        xmax += 5
        ymin -= 5
        ymax += 5
        box = QgsRectangle(xmin, ymin, xmax, ymax)
        box.grow(20)
        self.api.mainwindow.canvas.setExtent(box)
        self.api.mainwindow.canvas.refresh()
        self.api.mainwindow.showmap()
        RoamEvents.selectionchanged.emit({layer: [feature]})
Exemplo n.º 44
0
class ProjectsWidget(Ui_ListModules, QWidget):
    requestOpenProject = pyqtSignal(object)
    projectUpdate = pyqtSignal(object)
    search_for_updates = pyqtSignal()
    projectInstall = pyqtSignal(dict)

    def __init__(self, parent=None):
        super(ProjectsWidget, self).__init__(parent)
        self.setupUi(self)
        self.serverurl = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.moduleList)
        self.moduleList.itemClicked.connect(self.openProject)
        self.projectitems = {}
        self.project_base = None
        self.progressFrame.hide()

    def showEvent(self, event):
        self.search_for_updates.emit()

    def loadProjectList(self, projects):
        self.moduleList.clear()
        self.projectitems.clear()
        for project in projects:
            if not project.valid:
                roam.utils.warning("Project {0} is invalid because {1}".format(project.name, project.error))

            self.add_new_item(project.id, project, is_new=False, is_valid=project.valid)

    def show_new_updateable(self, updateprojects, newprojects):
        print updateprojects, newprojects
        for info in updateprojects:
            projectid = info['projectid']
            item = self.projectitems[projectid]
            widget = self.item_widget(item)
            widget.serverversion = info['version']
            widget.serverinfo = info

        for info in newprojects:
            projectid = info['projectid']
            if info['name'] in self.projectitems:
                self.update_item(projectid, info)
            else:
                self.add_new_item(projectid, info, is_new=True)

    def update_item(self, projectid, info):
        item = self.projectitems[projectid]
        item.setData(QListWidgetItem.UserType, info)
        widget = self.moduleList.itemWidget(item)
        widget.project = info
        widget.serverinfo = info

    def add_new_item(self, projectid, project, is_new=False, is_valid=True):
        item = QListWidgetItem(self.moduleList, QListWidgetItem.UserType)
        item.setData(QListWidgetItem.UserType, project)
        item.setSizeHint(QSize(150, 150))
        if not is_valid:
            item.setFlags(item.flags() & ~Qt.ItemIsEnabled)

        projectwidget = ProjectWidget(self.moduleList, project, is_new=is_new)
        projectwidget.install_project.connect(self.projectInstall.emit)
        projectwidget.update_project.connect(self.projectUpdate.emit)
        projectwidget.setEnabled(is_valid)
        projectwidget.serverinfo = project

        self.moduleList.addItem(item)
        self.moduleList.setItemWidget(item, projectwidget)

        self.projectitems[projectid] = item

    def item_widget(self, item):
        return self.moduleList.itemWidget(item)

    def openProject(self, item):
        # self.setDisabled(True)
        project = self.item_widget(item).project
        if isinstance(project, dict):
            return

        if not project.valid:
            return

        self.selectedProject = project
        self.requestOpenProject.emit(project)
        self.set_open_project(project)

    def set_open_project(self, currentproject):
        for projectid, item in self.projectitems.iteritems():
            widget = self.item_widget(item)
            if widget.is_new:
                continue

            project = widget.project
            if currentproject is None:
                widget.show_close(False)
            else:
                widget.show_close(currentproject.id == project.id)

    def project_installed(self, projectname):
        project = roam.project.Project.from_folder(os.path.join(self.project_base, projectname))
        item = self.projectitems[project.basefolder]
        widget = self.item_widget(item)
        widget.project = project
        widget.is_new = False
        widget.update_status("installed")

    def update_project_status(self, projectname, status):
        if status.lower() in ["complete", 'installed']:
            self.progressFrame.hide()
        else:
            self.progressFrame.show()
            self.statusLabel.setText("{}: {}".format(projectname, status))

        try:
            item = self.projectitems[projectname]
            widget = self.item_widget(item)
            widget.update_status(status)
        except KeyError:
            pass
Exemplo n.º 45
0
class SyncWidget(Ui_Form, QWidget):
    syncqueue = []
    def __init__(self, parent=None):
        super(SyncWidget, self).__init__(parent)
        self.setupUi(self)
        self.syncrunning = False
        self.syncallButton.hide()
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.scrollArea)
        self.flickcharm.activateOn(self.syncstatus)

    def load_application_sync(self):
        print "Load application sync"
        providers = list(roam.syncing.syncprovders())
        if not providers:
            return

        actionwidget = ActionPickerWidget()
        actionwidget.setTile("Roam Syncing")
        for provider in providers:
            action = QAction(None)
            action.setText(provider.name)
            action.setIcon(QIcon(":/icons/sync"))
            action.triggered.connect(partial(self.run, action, provider))
            actionwidget.addAction(action)
        self.syncwidgets.layout().addWidget(actionwidget)

    def loadprojects(self, projects):
        #root = self.synctree.invisibleRootItem()
        self.load_application_sync()
        for project in projects:
            providers = list(project.syncprovders())
            if not providers:
                continue

            actionwidget = ActionPickerWidget()
            actionwidget.setTile(project.name)
            for provider in providers:
                action = QAction(None)
                action.setText(provider.name)
                action.setIcon(QIcon(":/icons/sync"))
                action.triggered.connect(partial(self.run, action, provider))
                actionwidget.addAction(action)
            self.syncwidgets.layout().addWidget(actionwidget)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.syncwidgets.layout().addItem(spacerItem)

    def updatestatus(self, message):
        self.syncstatus.append(message)
        self.syncstatus.ensureCursorVisible()

    def updatewitherror(self, message):
        self.updatestatus('<b style="color:red">Error in sync: {}</b>'.format(message))
        self.updatestatus('')

    def updatecomplete(self):
        self.updatestatus('<b style="color:darkgreen">Sync complete</b>')
        self.updatestatus('')
        RoamEvents.sync_complete.emit()

    def runnext(self):
        try:
            provider = SyncWidget.syncqueue.pop(0)
            provider.syncComplete.connect(self.updatecomplete)
            provider.syncComplete.connect(self.runnext)
            provider.syncMessage.connect(self.updatestatus)
            provider.syncError.connect(self.updatewitherror)
            if provider.closeproject:
                RoamEvents.closeProject.emit(provider.project)
            provider.start()
        except IndexError:
            # If we get here we have run out of providers to run
            return

    def disconnect(self, provider):
        try:
            provider.syncComplete.disconnect()
            provider.syncMessage.disconnect()
            provider.syncStarted.disconnect()
            provider.syncError.disconnect()
        except TypeError:
            pass

    def syncfinished(self, action, provider):
        self.disconnect(provider)
        action.setText(provider.name)
        action.setEnabled(True)
        self.syncrunning = False

    def syncstarted(self, action, provider):
        self.updatestatus('<b style="font-size:large">Sync started for {}</h3>'.format(provider.name))
        action.setText('Running')
        action.setEnabled(False)
        self.syncrunning = True

    def run(self, action, provider):
        provider.syncStarted.connect(partial(self.syncstarted, action, provider))
        provider.syncFinished.connect(partial(self.syncfinished, action, provider))

        SyncWidget.syncqueue.append(provider)
        if self.syncrunning:
            action.setText("Pending")
        else:
            self.runnext()
Exemplo n.º 46
0
class FeatureFormWidget(Ui_Form, QWidget):
    # Raise the cancel event, takes a reason and a level
    cancel = pyqtSignal(str, int)
    featuresaved = pyqtSignal()
    featuredeleted = pyqtSignal()

    def __init__(self, parent=None):
        super(FeatureFormWidget, self).__init__(parent)
        self.setupUi(self)

        toolbar = QToolBar()
        size = QSize(48, 48)
        toolbar.setIconSize(size)
        style = Qt.ToolButtonTextUnderIcon
        toolbar.setToolButtonStyle(style)
        self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"), "Delete")
        self.actionDelete.triggered.connect(self.delete_feature)

        label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>'
        self.missingfieldsLabel = QLabel(label)
        self.missingfieldsLabel.hide()
        self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel)

        titlespacer = QWidget()
        titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        toolbar.addWidget(titlespacer)
        self.titlellabel = QLabel(label)
        self.titlellabel.setProperty("headerlabel", True)
        self.titlelabelaction = toolbar.addWidget(self.titlellabel)

        spacer = QWidget()
        spacer2 = QWidget()
        spacer2.setMinimumWidth(20)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        toolbar.addWidget(spacer)
        self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"), "Cancel")
        toolbar.addWidget(spacer2)
        self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save")
        self.actionSave.triggered.connect(self.save_feature)

        self.layout().insertWidget(0, toolbar)

        self.flickwidget = FlickCharm()
        self.flickwidget.activateOn(self.scrollArea)

        self.featureform = None
        self.values = {}
        self.config = {}
        self.feature = None

    def set_featureform(self, featureform):
        """
        Note: There can only be one feature form.  If you need to show another one make a new FeatureFormWidget
        """
        self.featureform = featureform
        self.titlellabel.setText(self.featureform.windowTitle())
        self.featureform.formvalidation.connect(self._update_validation)
        self.featureform.helprequest.connect(functools.partial(RoamEvents.helprequest.emit, self))
        self.featureform.showlargewidget.connect(RoamEvents.show_widget.emit)
        self.featureform.enablesave.connect(self.actionSave.setEnabled)
        self.featureform.enablesave.connect(self.actionSave.setVisible)
        self.featureform.rejected.connect(self.cancel.emit)

        self.featureformarea.layout().addWidget(self.featureform)

    def delete_feature(self):
        try:
            msg = self.featureform.deletemessage
        except AttributeError:
            msg = 'Do you really want to delete this feature?'

        box = DeleteFeatureDialog(msg)

        if not box.exec_():
            return

        try:
            self.featureform.delete()
        except featureform.DeleteFeatureException as ex:
            RoamEvents.raisemessage(*ex.error)

        self.featureform.featuredeleted(self.feature)
        self.featuredeleted.emit()

    def save_feature(self):
        try:
            self.featureform.save()
        except featureform.MissingValuesException as ex:
            RoamEvents.raisemessage(*ex.error)
            return
        except featureform.FeatureSaveException as ex:
            RoamEvents.raisemessage(*ex.error)

        self.featuresaved.emit()
        RoamEvents.featuresaved.emit()

    def set_config(self, config):
        self.config = config
        editmode = config['editmode']
        allowsave = config.get('allowsave', True)
        self.feature = config.get('feature', None)
        self.featureform.feature = self.feature
        self.featureform.editingmode = editmode
        self.actionDelete.setVisible(editmode)
        self.actionSave.setEnabled(allowsave)

    def _update_validation(self, passed):
        # Show the error if there is missing fields
        self.missingfieldaction.setVisible(not passed)

    def bind_values(self, values):
        self.values = values
        self.featureform.bindvalues(values)

    def after_load(self):
        self.featureform.loaded()

    def before_load(self):
        self.featureform.load(self.config['feature'], self.config['layers'], self.values)
Exemplo n.º 47
0
class InfoDock(infodock_widget, QWidget):
    featureupdated = pyqtSignal(object, object, list)
    resultscleared = pyqtSignal()

    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(self.handle_link)
        self.attributesView.page().setLinkDelegationPolicy(
            QWebPage.DelegateAllLinks)
        action = self.attributesView.pageAction(QWebPage.Copy)
        action.setShortcut(QKeySequence.Copy)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.editGeomButton.pressed.connect(self.editgeom)
        self.parent().installEventFilter(self)
        self.project = None
        self.startwidth = self.width()
        self.expaned = False
        self.layerList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.expandAction = QAction(QIcon(":/icons/expand"), "Expand Panel",
                                    self)
        self.expandAction.triggered.connect(self.change_expanded_state)

        self.navigateAction = QAction(QIcon(":/icons/navigate"),
                                      "Navigate To..", self)
        self.navigateAction.triggered.connect(self._navigate_to_selection)

        self.moreActionsButton.pressed.connect(self._show_more_actions)
        self.navwidget.mousePressEvent = self._sink
        self.bottomWidget.mousePressEvent = self._sink
        self.navwidget.mouseReleaseEvent = self._sink
        self.bottomWidget.mouseReleaseEvent = self._sink
        self.navwidget.mouseMoveEvent = self._sink
        self.bottomWidget.mouseMoveEvent = self._sink
        self.deleteFeatureButton.pressed.connect(self.delete_feature)
        self.deleteFeatureButton.setCheckable(False)

        self.quickInspectButton.hide()
        self.quickInspectButton.pressed.connect(self.quick_inspect)

        self.nextButton.pressed.connect(self.pagenext)
        self.prevButton.pressed.connect(self.pageback)

        RoamEvents.selectioncleared.connect(self.clearResults)
        RoamEvents.editgeometry_complete.connect(self.refreshcurrent)

    def _navigate_to_selection(self):
        feature = self.selection.feature
        geom = feature.geometry()
        point = geom.centroid().asPoint()
        if GPS.waypoint == point:
            GPS.waypoint = None
        else:
            GPS.waypoint = point

    def _show_more_actions(self):
        dlg = PickActionDialog()
        self.navigateAction.setEnabled(GPS.isConnected)
        if not GPS.isConnected:
            self.navigateAction.setText("Navigate To.. (No GPS)")
        else:
            self.navigateAction.setText("Navigate To..")

        dlg.addactions([self.expandAction, self.navigateAction])
        dlg.exec_()

    def delete_feature(self):
        cursor = self.selection
        RoamEvents.delete_feature(cursor.form, cursor.feature)

    def handle_link(self, url):
        if url.toString().endswith("/back"):
            self.pageback()
        elif url.toString().endswith("/next"):
            self.pagenext()
        else:
            RoamEvents.openurl.emit(url)

    def _sink(self, event):
        return

    def change_expanded_state(self):
        if self.expaned:
            self._collapse()
        else:
            self._expand()

    def mousePressEvent(self, event):
        pos = self.mapToParent(event.pos())
        newevent = QMouseEvent(event.type(), pos, event.button(),
                               event.buttons(), event.modifiers())
        self.parent().mousePressEvent(newevent)

    def mouseReleaseEvent(self, event):
        pos = self.mapToParent(event.pos())
        newevent = QMouseEvent(event.type(), pos, event.button(),
                               event.buttons(), event.modifiers())
        self.parent().mouseReleaseEvent(newevent)

    def mouseMoveEvent(self, event):
        pos = self.mapToParent(event.pos())
        newevent = QMouseEvent(event.type(), pos, event.button(),
                               event.buttons(), event.modifiers())
        self.parent().mouseMoveEvent(newevent)

    def _expand(self):
        self.resize(self.parent().width() - 10, self.parent().height())
        self.move(10, 0)
        self.expaned = True
        self.expandAction.setText("Collapse Panel")

    def _collapse(self):
        self.resize(self.startwidth, self.parent().height())
        self.move(self.parent().width() - self.startwidth, 0)
        self.expaned = False
        self.expandAction.setText("Expand Panel")

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self._collapse()

        return super(InfoDock, self).eventFilter(object, event)

    def close(self):
        RoamEvents.selectioncleared.emit()
        super(InfoDock, self).close()

    def event(self, event):
        if event.type() == QEvent.Gesture:
            gesture = event.gesture(Qt.SwipeGesture)
            if gesture:
                self.pagenext()
        return QWidget.event(self, event)

    @property
    def selection(self):
        item = self.layerList.item(self.layerList.currentRow())
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        return cursor

    def openform(self):
        cursor = self.selection
        tools = self.project.layer_tools(cursor.layer)
        if 'inspection' in tools:
            config = tools['inspection']
            form, feature = self.get_inspection_config(cursor.feature, config)
            editmode = False
        else:
            form = cursor.form
            feature = cursor.feature
            editmode = True

        RoamEvents.load_feature_form(form, feature, editmode)

    def quick_inspect(self):
        cursor = self.selection
        tools = self.project.layer_tools(cursor.layer)
        config = tools['inspection']
        form, feature = self.get_inspection_config(cursor.feature, config)
        editmode = False
        form.suppressform = True
        RoamEvents.load_feature_form(form, feature, editmode)
        # Leaking state is leaking.  But this is what we have for now.
        form.suppressform = False

    def get_inspection_config(self, current_feature, config):
        form = config['form']
        newform = self.project.form_by_name(form)
        if config.get('mode', "copy").lower() == 'copy':
            geom = current_feature.geometry()
            mappings = config.get('field_mapping', {})
            data = {}
            for fieldfrom, fieldto in mappings.iteritems():
                data[fieldto] = current_feature[fieldfrom]

            newgeom = QgsGeometry(geom)
            newfeature = newform.new_feature(geometry=newgeom, data=data)

            return newform, newfeature
        else:
            raise NotImplementedError("Only copy mode supported currently")

    def editgeom(self):
        cursor = self.selection
        RoamEvents.editgeometry.emit(cursor.form, cursor.feature)
        self.editGeomButton.setEnabled(False)
        self.deleteFeatureButton.setEnabled(False)

    def pageback(self):
        cursor = self.selection
        cursor.back()
        self.update(cursor)

    def pagenext(self):
        cursor = self.selection
        cursor.next()
        self.update(cursor)

    def layerIndexChanged(self, index):
        item = self.layerList.item(index)
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        self.update(cursor)

    def setResults(self, results, forms, project):
        lastrow = self.layerList.currentRow()
        if lastrow == -1:
            lastrow = 0

        self.clearResults()
        self.forms = forms
        self.project = project

        for layer, features in results.iteritems():
            if features:
                self._addResult(layer, features)

        self.layerList.setCurrentRow(lastrow)
        self.layerList.setMinimumWidth(
            self.layerList.sizeHintForColumn(0) + 20)
        size = 0
        for n in range(self.layerList.count()):
            size += self.layerList.sizeHintForRow(n)
        self.layerList.setMinimumHeight(size)
        self.layerList.setMaximumHeight(size)
        self.navwidget.show()

    def show(self):
        if self.layerList.count() > 0:
            super(InfoDock, self).show()
        else:
            self.hide()

    def _addResult(self, layer, features):
        layername = layer.name()
        forms = self.forms.get(layername, [])
        if not forms:
            item = QListWidgetItem(QIcon(), layername, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features))
            return

        for form in forms:
            selectname = self.project.selectlayer_name(form.layername)
            if selectname == layername:
                itemtext = "{} \n ({})".format(layername, form.label)
            else:
                itemtext = selectname
            icon = QIcon(form.icon)
            item = QListWidgetItem(icon, itemtext, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features, form))

    def refreshcurrent(self):
        self.update(self.selection)

    def update(self, cursor):
        if cursor is None:
            return

        try:
            feature = cursor.feature
        except NoFeature as ex:
            utils.exception(ex)
            return

        form = cursor.form
        layer = cursor.layer

        clear_image_cache()

        self.countLabel.setText(str(cursor))

        info1, results = self.generate_info("info1",
                                            self.project,
                                            layer,
                                            feature.id(),
                                            feature,
                                            countlabel=str(cursor))
        info2, _ = self.generate_info("info2",
                                      self.project,
                                      layer,
                                      feature.id(),
                                      feature,
                                      lastresults=results[0])

        if form:
            name = "{}".format(layer.name(), form.label)
        else:
            name = layer.name()

        info = dict(TITLE=name, INFO1=info1, INFO2=info2)

        html = updateTemplate(info, infotemplate)

        self.attributesView.setHtml(html, templates.baseurl)
        tools = self.project.layer_tools(layer)
        hasform = not form is None
        print tools
        editattributes = 'edit_attributes' in tools or 'inspection' in tools or hasform
        print editattributes
        editgeom = 'edit_geom' in tools and hasform
        deletefeature = 'delete' in tools and hasform
        self.deleteFeatureButton.setVisible(deletefeature)
        self.quickInspectButton.setVisible('inspection' in tools)
        self.editButton.setVisible(editattributes)
        self.editGeomButton.setVisible(editgeom)
        self.featureupdated.emit(layer, feature, cursor.features)

    def generate_info(self,
                      infoblock,
                      project,
                      layer,
                      mapkey,
                      feature,
                      countlabel=None,
                      lastresults=None):
        infoblockdef = project.info_query(infoblock, layer.name())
        isinfo1 = infoblock == "info1"

        if not infoblockdef:
            if isinfo1:
                infoblockdef = {}
                infoblockdef['type'] = 'feature'
            else:
                return None, []

        if isinfo1:
            caption = infoblockdef.get('caption', "Record")
        else:
            caption = infoblockdef.get('caption', "Related Record")

        results = []
        error = None
        infotype = infoblockdef.get('type', 'feature')
        if infotype == 'sql':
            try:
                queryresults = self.results_from_query(infoblockdef,
                                                       layer,
                                                       feature,
                                                       mapkey,
                                                       lastresults=lastresults)
                if isinfo1 and not queryresults:
                    # If there is no results from the query and we are a info 1 block we grab from the feature.
                    results.append(self.results_from_feature(feature))
                else:
                    results = queryresults
            except database.DatabaseException as ex:
                RoamEvents.raisemessage("Query Error", ex.message, 3)
                utils.error(ex.message)
                if not isinfo1:
                    error = "<b> Error: {} <b>".format(ex.msg)
                else:
                    results.append(self.results_from_feature(feature))

        elif infotype == 'feature':
            featuredata = self.results_from_feature(feature)
            excludedfields = infoblockdef.get('hidden', [])
            for field in excludedfields:
                try:
                    del featuredata[field]
                except KeyError:
                    pass
            results.append(featuredata)
        else:
            return None, []

        blocks = []
        for count, result in enumerate(results, start=1):
            if isinfo1 and count == 1:
                countblock = countblocktemplate.substitute(count=countlabel)
            else:
                countblock = ''

            fields = result.keys()
            attributes = result.values()
            rows = generate_rows(fields,
                                 attributes,
                                 imagepath=self.project.image_folder)
            try:
                caption = caption.format(**dict(zip(fields, attributes)))
            except KeyError:
                pass

            blocks.append(
                updateTemplate(
                    dict(ROWS=rows, HEADER=caption, CONTROLS=countblock),
                    infoblocktemplate))
        if error:
            return error, []

        return '<br>'.join(blocks), results

    def results_from_feature(self, feature):
        attributes = feature.attributes()
        fields = [field.name().lower() for field in feature.fields()]
        return OrderedDict(zip(fields, attributes))

    def results_from_query(self,
                           infoblockdef,
                           layer,
                           feature,
                           mapkey,
                           lastresults=None):
        def get_key():
            try:
                keycolumn = infoblockdef['mapping']['mapkey']
                if keycolumn == 'from_info1':
                    if 'mapkey' in lastresults:
                        return lastresults['mapkey']
                    else:
                        return []
                else:
                    return feature[keycolumn]
            except KeyError:
                return mapkey

        def get_layer():
            connection = infoblockdef.get('connection', "from_layer")
            if isinstance(connection, dict):
                return layer_by_name(connection['layer'])
            elif connection == "from_layer":
                return layer
            else:
                raise NotImplementedError(
                    "{} is not a supported connection type".format(connection))

        if not lastresults:
            lastresults = {}

        sql = infoblockdef['query']
        layer = get_layer()

        db = database.Database.fromLayer(layer)
        mapkey = get_key()
        attributes = values_from_feature(feature, safe_names=True)
        attributes['mapkey'] = mapkey
        # Run the SQL text though the QGIS expression engine first.
        sql = QgsExpression.replaceExpressionText(sql, feature, layer)
        results = db.query(sql, **attributes)
        results = list(results)
        return results

    def clearResults(self):
        self.layerList.clear()
        self.attributesView.setHtml('')
        self.editButton.setVisible(False)
        self.editGeomButton.setEnabled(True)
        self.editButton.setEnabled(True)
        self.deleteFeatureButton.setEnabled(True)
        self.navwidget.hide()
Exemplo n.º 48
0
class InfoDock(infodock_widget, QWidget):
    requestopenform = pyqtSignal(object, QgsFeature)
    featureupdated = pyqtSignal(object, object, list)
    resultscleared = pyqtSignal()

    def __init__(self, parent):
        super(InfoDock, self).__init__(parent)
        self.setupUi(self)
        self.forms = {}
        self.charm = FlickCharm()
        self.charm.activateOn(self.attributesView)
        self.layerList.currentRowChanged.connect(self.layerIndexChanged)
        self.attributesView.linkClicked.connect(openimage)
        self.attributesView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.grabGesture(Qt.SwipeGesture)
        self.setAttribute(Qt.WA_AcceptTouchEvents)
        self.editButton.pressed.connect(self.openform)
        self.parent().installEventFilter(self)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            width = self.parent().width() * 40 / 100
            self.resize(width, self.parent().height())
            self.move(self.parent().width() - self.width() - 1, 1)

        return object.eventFilter(object, event)

    def close(self):
        self.clearResults()
        super(InfoDock, self).close()

    def event(self, event):
        if event.type() == QEvent.Gesture:
            gesture = event.gesture(Qt.SwipeGesture)
            if gesture:
                self.pagenext()
        return QWidget.event(self, event)

    @property
    def selection(self):
        item = self.layerList.item(self.layerList.currentRow())
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        return cursor

    def openform(self):
        cursor = self.selection
        self.requestopenform.emit(cursor.form, cursor.feature)

    def pageback(self):
        cursor = self.selection
        cursor.back()
        self.update(cursor)

    def pagenext(self):
        cursor = self.selection
        cursor.next()
        self.update(cursor)

    def layerIndexChanged(self, index):
        item = self.layerList.item(index)
        if not item:
            return

        cursor = item.data(Qt.UserRole)
        self.update(cursor)

    def setResults(self, results, forms):
        self.clearResults()
        self.forms = forms

        for layer, features in results.iteritems():
            if features:
                self._addResult(layer, features)

        self.layerList.setCurrentRow(0)
        self.layerList.setMinimumWidth(self.layerList.sizeHintForColumn(0) + 20)
        self.navwidget.show()

    def show(self):
        if self.layerList.count() > 0:
            super(InfoDock, self).show()
        else:
            self.hide()

    def _addResult(self, layer, features):
        layername = layer.name()
        forms = self.forms.get(layername, [])
        if not forms:
            item = QListWidgetItem(QIcon(), layername, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features))
            return

        for form in forms:
            itemtext = "{} ({})".format(layername, form.label)
            icon = QIcon(form.icon)
            item = QListWidgetItem(icon, itemtext, self.layerList)
            item.setData(Qt.UserRole, FeatureCursor(layer, features, form))

    def update(self, cursor):
        global image
        images = {}
        feature = cursor.feature
        fields = [field.name() for field in feature.fields()]
        data = OrderedDict()

        items = []
        for field, value in zip(fields, feature.attributes()):
            data[field] = value
            item = "<tr><th>{0}</th> <td>${{{0}}}</td></tr>".format(field)
            items.append(item)
        rowtemple = Template("".join(items))
        rowshtml = updateTemplate(data, rowtemple)

        form = cursor.form
        layer = cursor.layer
        if form:
            name = "{}".format(layer.name(), form.label)
        else:
            name = layer.name()

        info = dict(TITLE=name, ROWS=rowshtml)

        html = updateTemplate(info, template)
        base = os.path.dirname(os.path.abspath(__file__))
        baseurl = QUrl.fromLocalFile(base + "\\")

        if form:
            displaytext = form.settings.get("display", None)
            display = QgsExpression.replaceExpressionText(displaytext, cursor.feature, layer)
        else:
            display = str(feature[0])

        self.countlabel.setText(str(cursor))
        self.displaylabel.setText(display)
        self.attributesView.setHtml(html, baseurl)
        self.editButton.setVisible(not form is None)
        self.featureupdated.emit(layer, cursor.feature, cursor.features)

    def clearResults(self):
        self.layerList.clear()
        self.attributesView.setHtml("")
        self.editButton.setVisible(False)
        self.resultscleared.emit()
        self.navwidget.hide()
Exemplo n.º 49
0
class ProjectsWidget(Ui_ListModules, QWidget):
    requestOpenProject = pyqtSignal(object)
    projectUpdate = pyqtSignal(object, object)
    search_for_updates = pyqtSignal()
    projectInstall = pyqtSignal(dict)

    def __init__(self, parent=None):
        super(ProjectsWidget, self).__init__(parent)
        self.setupUi(self)
        self.serverurl = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.moduleList)
        self.moduleList.itemClicked.connect(self.openProject)
        self.projectitems = {}
        self.project_base = None

    def showEvent(self, event):
        self.search_for_updates.emit()

    def loadProjectList(self, projects):
        self.moduleList.clear()
        self.projectitems.clear()
        for project in projects:
            if not project.valid:
                roam.utils.warning("Project {} is invalid because {}".format(project.name, project.error))
                continue

            self.add_new_item(project.name, project, is_new=False)

    def show_new_updateable(self, updateprojects, newprojects):
        print updateprojects, newprojects
        for project, info in updateprojects:
            item = self.projectitems[project.name]
            widget = self.item_widget(item)
            widget.serverversion = info['version']

        for info in newprojects:
            if info['name'] in self.projectitems:
                self.update_item(info['name'], info)
            else:
                self.add_new_item(info['name'], info, is_new=True)

    def update_item(self, name, info):
        item = self.projectitems[name]
        item.setData(QListWidgetItem.UserType, info)
        widget = self.moduleList.itemWidget(item)
        widget.project = info
    
    def add_new_item(self, name, project, is_new=False):
        item = QListWidgetItem(self.moduleList, QListWidgetItem.UserType)
        item.setData(QListWidgetItem.UserType, project)
        item.setSizeHint(QSize(150, 150))

        projectwidget = ProjectWidget(self.moduleList, project, is_new=is_new)
        projectwidget.install_project.connect(self.projectInstall.emit)
        projectwidget.update_project.connect(self.projectUpdate.emit)

        self.moduleList.addItem(item)
        self.moduleList.setItemWidget(item, projectwidget)

        self.projectitems[name] = item

    def item_widget(self, item):
        return self.moduleList.itemWidget(item)

    def openProject(self, item):
        # self.setDisabled(True)
        project = self.item_widget(item).project
        if isinstance(project, dict):
            return

        self.selectedProject = project
        self.requestOpenProject.emit(project)
        self.set_open_project(project)

    def set_open_project(self, currentproject):
        for project, item in self.projectitems.iteritems():
            widget = self.item_widget(item)
            project = widget.project
            if currentproject and not isinstance(project, dict):
                showclose = currentproject.basefolder == project.basefolder
            else:
                showclose = False
            widget.show_close(showclose)

    def project_installed(self, projectname):
        project = roam.project.Project.from_folder(os.path.join(self.project_base, projectname))
        item = self.projectitems[project.basefolder]
        widget = self.item_widget(item)
        widget.project = project
        widget.is_new = False
        widget.update_status("installed")

    def update_project_status(self, projectname, status):
        item = self.projectitems[projectname]
        widget = self.item_widget(item)
        widget.update_status(status)
Exemplo n.º 50
0
class SearchPlugin(widget, base, Page):
    title = "Search"
    icon = resolve("search.svg")

    def __init__(self, api, parent=None):
        super(SearchPlugin, self).__init__(parent)
        self.setupUi(self)
        self.api = api
        self.project = None
        self.dbpath = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.resultsView)
        self.searchbox.textChanged.connect(self.search)
        self.searchbox.installEventFilter(self)
        self.resultsView.itemClicked.connect(self.jump_to)
        self.rebuildLabel.linkActivated.connect(self.rebuild_index)
        self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
        self.indexbuilder = None
        self.indexthread = None

    def fuzzy_changed(self, state):
        self.search(self.searchbox.text())

    def index_built(self, dbpath, timing):
        self.dbpath = dbpath
        self.resultsView.clear()
        self.searchbox.setEnabled(True)
        print "Index built in: {} seconds".format(timing)

    def eventFilter(self, object, event):
        if event.type() == QEvent.FocusIn:
            RoamEvents.openkeyboard.emit()
        return False

    @property
    def db(self):
        db = sqlite3.connect(self.dbpath)
        db.create_function("rank", 1, make_rank_func((1., .1, 0, 0)))
        return db

    def project_loaded(self, project):
        self.project = project
        self.build_index(project)

    def rebuild_index(self):
        self.build_index(self.project)

    def build_index(self, project):
        self.searchbox.setEnabled(False)
        self.resultsView.setEnabled(False)
        self.resultsView.addItem("Just let me build the search index first....")

        self.indexthread = QThread()
        self.indexbuilder = IndexBuilder(project.folder, project.settings.get("search", {}))
        self.indexbuilder.moveToThread(self.indexthread)

        self.indexbuilder.indexBuilt.connect(self.index_built)
        self.indexbuilder.finished.connect(self.indexthread.quit)
        self.indexthread.started.connect(self.indexbuilder.build_index)
        self.indexthread.finished.connect(self.indexbuilder.quit)

        print "building index"
        self.indexthread.start()

    def search(self, text):
        db = self.db
        c = db.cursor()
        self.resultsView.clear()
        self.resultsView.setEnabled(False)
        if not text:
            return

        if self.fuzzyCheck.isChecked():
            search = "* ".join(text.split()) + "*"
        else:
            search = text
        query = c.execute("""SELECT layer, featureid, snippet(search, '[',']') as snippet
                            FROM search
                            JOIN featureinfo on search.docid = featureinfo.id
                            WHERE search match '{}' LIMIT 100""".format(search)).fetchall()
        for layer, featureid, snippet in query:
            item = QListWidgetItem()
            text = "{}\n {}".format(layer, snippet.replace('\n', ' '))
            item.setText(text)
            item.setData(Qt.UserRole, (layer, featureid, snippet))
            self.resultsView.addItem(item)

        self.resultsView.setEnabled(True)

        if self.resultsView.count() == 0:
            self.resultsView.addItem("No Results")
        db.close()

    def jump_to(self, item):
        data = item.data(32)
        layername, fid = data[0], data[1]
        layer = roam.api.utils.layer_by_name(layername)
        layer.select(fid)
        feature = layer.selectedFeatures()[0]
        self.api.mainwindow.canvas.zoomToSelected(layer)
        layer.removeSelection()
        self.api.mainwindow.showmap()
        RoamEvents.selectionchanged.emit({layer: [feature]})