Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unwanted deps #273

Merged
merged 4 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ nix-result/
data
core
app.py
/geest.zip
946 changes: 946 additions & 0 deletions export.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion geest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#from .geest import Geest
#from .core import RenderQueue, setting
from .core import setting, JSONValidator
from .core import setting #, JSONValidator
from .utilities import resources_path
from .gui import GeestOptionsFactory, GeestDock

Expand Down
9 changes: 1 addition & 8 deletions geest/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,5 @@
from .constants import APPLICATION_NAME
from .settings import setting, set_setting

#from .animation_controller import (
# MapMode,
# AnimationController,
# InvalidAnimationParametersException,
#)
from .default_settings import default_settings
from .json_validator import JSONValidator
#from .movie_creator import MovieFormat, MovieCommandGenerator, MovieCreationTask
#from .render_queue import RenderJob, RenderQueue
#from .json_validator import JSONValidator
2 changes: 2 additions & 0 deletions geest/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
from .geest_dock import GeestDock
from .geest_treeview import JsonTreeItem, JsonTreeModel, CustomTreeView
from .setup_panel import SetupPanel
from .tree_panel import TreePanel
from .layer_detail_dialog import LayerDetailDialog
5 changes: 5 additions & 0 deletions geest/gui/dialogs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .base_dialog import BaseDialog
from .osm_downloader_dialog import OSMDownloaderDialog
from .index_score_dialog import IndexScoreDialog

__all__ = ['BaseDialog', 'OSMDownloaderDialog', 'IndexScoreDialog']
88 changes: 88 additions & 0 deletions geest/gui/dialogs/base_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from abc import ABC, abstractmethod
from qgis.PyQt.QtWidgets import QDialog, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
from qgis.PyQt.QtCore import Qt

from GEEST2.geest.gui.widgets.widget_factory import WidgetFactory


class BaseDialog(QDialog, ABC):
def __init__(self, input_specs: dict, on_accept_callback, parent=None):
"""
Initialize the base dialog.

:param input_specs: Dictionary containing dialog specifications.
:param on_accept_callback: Callback function to handle inputs upon acceptance.
:param parent: Parent widget.
"""
super().__init__(parent)
self.input_specs = input_specs
self.widgets = {}
self.on_accept_callback = on_accept_callback
self.init_ui()

def init_ui(self):
# Set dialog properties
self.setWindowTitle(self.input_specs.get('title', 'Dialog'))
self.layout = QVBoxLayout()
self.setLayout(self.layout)

# Iterate over input specifications to create widgets
for element in self.input_specs.get('elements', []):
widget_type = element.get('type')
label_text = element.get('label', '')
widget = self.create_widget(widget_type, element)

if label_text:
label = QLabel(label_text)
label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.layout.addWidget(label)

if widget:
self.layout.addWidget(widget)
self.widgets[element.get('name')] = widget

# Add dialog buttons
self.add_buttons()

def add_buttons(self):
button_layout = QHBoxLayout()
self.ok_button = QPushButton("OK")
self.cancel_button = QPushButton("Cancel")
self.ok_button.clicked.connect(self.handle_accept)
self.cancel_button.clicked.connect(self.reject)
button_layout.addStretch()
button_layout.addWidget(self.ok_button)
button_layout.addWidget(self.cancel_button)
self.layout.addLayout(button_layout)

def create_widget(self, widget_type, spec):
return WidgetFactory.create_widget(widget_type, spec, self)

def get_inputs(self):
inputs = {}
for name, widget in self.widgets.items():
spec = next((elem for elem in self.input_specs['elements'] if elem['name'] == name), None)
if spec:
inputs[name] = WidgetFactory.get_widget_value(widget, spec)
return inputs

def handle_accept(self):
if self.validate_inputs():
inputs = self.get_inputs()
self.on_accept_callback(inputs)
self.accept()
else:
# handle validation failure
pass

@staticmethod
def validate_inputs():
# input validation happens here
return True

@abstractmethod
def process_inputs(self, inputs: dict):
"""
This must be implemented by derived classes!
"""
pass
28 changes: 28 additions & 0 deletions geest/gui/dialogs/index_score_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from .base_dialog import BaseDialog

class IndexScoreDialog(BaseDialog):
def __init__(self, on_accept_callback, parent=None):
input_specs = {
'title': 'Index Score Configuration',
'elements': [
{
'type': 'doublespinbox',
'label': 'Default Value',
'name': 'default_value',
'min': 0.0,
'max': 100.0,
'decimals': 2,
'default': 50.0
},
{
'type': 'spinbox',
'label': 'Allowed Range',
'name': 'allowed_range',
'min': 1,
'max': 10,
'default': 5
},
# other widgettes go here
]
}
super().__init__(input_specs, on_accept_callback, parent)
26 changes: 26 additions & 0 deletions geest/gui/dialogs/osm_downloader_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from .base_dialog import BaseDialog

class OSMDownloaderDialog(BaseDialog):
def __init__(self, on_accept_callback, parent=None):
input_specs = {
'title': 'OSM Downloader',
'elements': [
{
'type': 'radiobutton',
'label': 'Data Source',
'name': 'data_source',
'options': [
{'label': 'Manual Input', 'id': 'manual', 'checked': True},
{'label': 'Download from OSM', 'id': 'osm'}
]
},
{
'type': 'lineedit',
'label': 'OSM Query',
'name': 'osm_query',
'default': 'highway=primary'
},
# more weedjits here
]
}
super().__init__(input_specs, on_accept_callback, parent)
2 changes: 1 addition & 1 deletion geest/gui/geest_dock.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .setup_panel import SetupPanel
from .tree_panel import TreePanel
from .layer_detail_dialog import LayerDetailDialog
from ..utilities import resources_path
from geest.utilities import resources_path


class GeestDock(QDockWidget):
Expand Down
15 changes: 11 additions & 4 deletions geest/gui/geest_treeview.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,19 @@ def setData(self, index, value, role=Qt.EditRole):

def flags(self, index):
"""Allow editing of the name and weighting columns."""

#Override the flags method to allow specific columns to be editable.

if not index.isValid():
return Qt.NoItemFlags

item = index.internalPointer()
if index.column() == 0 or index.column() == 2:
# Allow editing for the first column (name) and third column (weighting)
return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
return Qt.ItemIsSelectable | Qt.ItemIsEnabled
# For example, only allow editing for the first and second columns
if index.column() == 0 or index.column() == 1:
return Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled

return Qt.ItemIsSelectable | Qt.ItemIsEnabled

def update_font_color(self, item, color):
"""Update the font color of an item."""
item.font_color = color
Expand Down
2 changes: 1 addition & 1 deletion geest/gui/setup_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
)
from qgis.PyQt.QtCore import QFileInfo, QSettings, QVariant
from qgis.PyQt.QtGui import QPixmap
from ..utilities import resources_path
from geest.utilities import resources_path


class SetupPanel(QWidget):
Expand Down
18 changes: 17 additions & 1 deletion geest/gui/tree_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .geest_treeview import CustomTreeView, JsonTreeModel
from .setup_panel import SetupPanel
from .layer_detail_dialog import LayerDetailDialog
from ..utilities import resources_path
from geest.utilities import resources_path
from geest.core import set_setting, setting

class TreePanel(QWidget):
Expand Down Expand Up @@ -115,6 +115,22 @@ def __init__(self, parent=None, json_file=None):
button_bar.addWidget(self.edit_toggle) # Add the edit toggle
layout.addLayout(button_bar)
self.setLayout(layout)

def edit(self, index, trigger, event):
"""
Override the edit method to enable editing only on the column that was clicked.
"""
# Get the column that was clicked
column = index.column()

# Only allow editing on specific columns (e.g., column 0, 1, etc.)
if column == 0: # Only make the first column editable
return super().edit(index, trigger, event)
elif column == 2: # And the third column editable
return super().edit(index, trigger, event)

# Return False if the column shouldn't be editable
return False

def load_json(self):
"""Load the JSON data from the file."""
Expand Down
3 changes: 3 additions & 0 deletions geest/gui/widgets/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .widget_factory import WidgetFactory

__all__ = ['WidgetFactory']
77 changes: 77 additions & 0 deletions geest/gui/widgets/widget_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from qgis.PyQt.QtWidgets import (
QDoubleSpinBox, QSpinBox, QLineEdit, QComboBox, QRadioButton, QButtonGroup,
QFileDialog, QWidget, QHBoxLayout
)
from qgis.gui import QgsLayerComboBox
from qgis.core import QgsMapLayer

class WidgetFactory:
@staticmethod
def create_widget(widget_type, spec, parent):
if widget_type == 'doublespinbox':
widget = QDoubleSpinBox(parent)
widget.setRange(spec.get('min', -1e10), spec.get('max', 1e10))
widget.setDecimals(spec.get('decimals', 2))
widget.setValue(spec.get('default', 0.0))
return widget
elif widget_type == 'spinbox':
widget = QSpinBox(parent)
widget.setRange(spec.get('min', -1e9), spec.get('max', 1e9))
widget.setValue(spec.get('default', 0))
return widget
elif widget_type == 'lineedit':
widget = QLineEdit(parent)
widget.setText(spec.get('default', ''))
return widget
elif widget_type == 'dropdown':
widget = QComboBox(parent)
options = spec.get('options', [])
widget.addItems(options)
default = spec.get('default')
if default in options:
widget.setCurrentText(default)
elif options:
widget.setCurrentText(options[0])
return widget
elif widget_type == 'radiobutton':
button_group = QButtonGroup(parent)
layout = QHBoxLayout()
container = QWidget(parent)
container.setLayout(layout)
for option in spec.get('options', []):
rb = QRadioButton(option['label'])
rb.setChecked(option.get('checked', False))
button_group.addButton(rb, id=option.get('id'))
layout.addWidget(rb)
container.button_group = button_group # Attach the button group for retrieval
return container
elif widget_type == 'layerselector':
widget = QgsLayerComboBox(parent)
layer_type = spec.get('layer_type', 'vector') # can be vector or raster
if layer_type == 'vector':
widget.setFilters(QgsMapLayer.VectorLayer)
elif layer_type == 'raster':
widget.setFilters(QgsMapLayer.RasterLayer)
widget.setCurrentLayer(spec.get('default_layer', None))
return widget
# more widgets go here
else:
return None

@staticmethod
def get_widget_value(widget, spec):
widget_type = spec.get('type')
if widget_type in ['doublespinbox', 'spinbox']:
return widget.value()
elif widget_type == 'lineedit':
return widget.text()
elif widget_type == 'dropdown':
return widget.currentText()
elif widget_type == 'radiobutton':
checked_button = widget.button_group.checkedButton()
return checked_button.text() if checked_button else None
elif widget_type == 'layerselector':
layer = widget.currentLayer()
return layer.name() if layer else None
else:
return None
File renamed without changes.
Loading