Skip to content

Commit

Permalink
Improve pasting data from Excel (#2918)
Browse files Browse the repository at this point in the history
  • Loading branch information
soininen authored Aug 19, 2024
2 parents cdec94b + b02b085 commit f593c2c
Show file tree
Hide file tree
Showing 100 changed files with 1,111 additions and 1,134 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
- Database editor's hamburger menu has been converted into a menubar beneath the tab bar. The URL toolbar has also
been replaced with a toolbar that houses different buttons.
- One dimensional entities can now also be added through *Parameter value* and *Entity alternative* tables.
- Special data types like dates, times and booleans are now properly pasted from Excel.

### Deprecated

Expand Down
7 changes: 2 additions & 5 deletions spinetoolbox/execution_managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ class QProcessExecutionManager(ExecutionManager):
"""Class to manage tool instance execution using a PySide6 QProcess."""

def __init__(self, logger, program="", args=None, silent=False, semisilent=False):
"""Class constructor.
"""
Args:
logger (LoggerInterface): a logger instance
program (str): Path to program to run in the subprocess (e.g. julia.exe)
Expand Down Expand Up @@ -180,9 +179,7 @@ def on_process_error(self, process_error):
def teardown_process(self):
"""Tears down the QProcess in case a QProcess.ProcessError occurred.
Emits execution_finished signal."""
if not self._process:
pass
else:
if self._process:
out = str(self._process.readAllStandardOutput().data(), "utf-8", errors="replace")
errout = str(self._process.readAllStandardError().data(), "utf-8", errors="replace")
if out is not None:
Expand Down
15 changes: 12 additions & 3 deletions spinetoolbox/mvcmodels/array_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Contains model for the Array editor widget."""
import locale
from numbers import Number
from typing import Type
import numpy
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
from spinedb_api import Array, ParameterValueFormatError, SpineDBAPIError, from_database
Expand All @@ -38,6 +39,10 @@ def __init__(self, parent):
self._data_type = float
self._index_name = Array.DEFAULT_INDEX_NAME

@property
def data_type(self) -> Type:
return self._data_type

def array(self):
"""Returns the array modeled by this model."""
return Array(self._data, self._data_type, self._index_name)
Expand All @@ -53,7 +58,7 @@ def batch_set_data(self, indexes, values):
return
top_row = indexes[0].row()
bottom_row = top_row
indexes, values = self._convert_to_data_type(indexes, values)
# indexes, values = self._convert_to_data_type(indexes, values)
if not indexes:
return
for index, value in zip(indexes, values):
Expand All @@ -63,8 +68,8 @@ def batch_set_data(self, indexes, values):
if row == len(self._data):
self.insertRow(len(self._data))
self._data[row] = value
top_left = self.index(top_row, 0)
bottom_right = self.index(bottom_row, 0)
top_left = self.index(top_row, 1)
bottom_right = self.index(bottom_row, 1)
self.dataChanged.emit(
top_left,
bottom_right,
Expand All @@ -86,6 +91,8 @@ def _convert_to_data_type(self, indexes, values):
Returns:
tuple: indexes and converted values
"""
if all(isinstance(v, self._data_type) for v in values):
return indexes, values
filtered = []
converted = []
if self._data_type == float:
Expand Down Expand Up @@ -113,6 +120,8 @@ def _convert_to_data_type(self, indexes, values):
continue
except SpineDBAPIError:
pass
if not isinstance(value, str):
continue
try:
data = from_database(value, self._data_type.type_())
if isinstance(data, self._data_type):
Expand Down
4 changes: 4 additions & 0 deletions spinetoolbox/mvcmodels/indexed_value_table_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def columnCount(self, parent=QModelIndex()):
"""Returns the number of columns which is two."""
return 2

def column_type(self, column):
"""Returns column's type."""
raise NotImplementedError()

def data(self, index, role=Qt.ItemDataRole.DisplayRole):
"""Returns the data at index for given role."""
if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole):
Expand Down
8 changes: 8 additions & 0 deletions spinetoolbox/mvcmodels/time_pattern_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
class TimePatternModel(IndexedValueTableModel):
"""A model for time pattern type parameter values."""

def column_type(self, column):
"""Returns column's type."""
if column == 0:
return str
if column == 1:
return float
raise RuntimeError("Logic error: column out of bounds")

def flags(self, index):
"""Returns flags at index."""
if not index.isValid():
Expand Down
6 changes: 6 additions & 0 deletions spinetoolbox/mvcmodels/time_series_model_fixed_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ def __init__(self, series, parent):
super().__init__(series, parent)
self.locale = QLocale()

def column_type(self, column):
"""Returns column's type."""
if column == 1:
return float
raise RuntimeError("Logic error: column out of bounds")

def flags(self, index):
"""Returns flags at index."""
if not index.isValid():
Expand Down
18 changes: 13 additions & 5 deletions spinetoolbox/mvcmodels/time_series_model_variable_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
class TimeSeriesModelVariableResolution(IndexedValueTableModel):
"""A model for variable resolution time series type parameter values."""

def column_type(self, column):
"""Returns column's type."""
if column == 0:
return np.datetime64
if column == 1:
return float
raise RuntimeError("Logic error: column out of bounds")

def flags(self, index):
"""Returns the flags for given model index."""
if not index.isValid():
Expand Down Expand Up @@ -164,20 +172,20 @@ def batch_set_data(self, indexes, values):
indexes (Sequence): a sequence of model indexes
values (Sequence): a sequence of datetimes/floats corresponding to the indexes
"""
modified_rows = []
modified_columns = []
modified_rows = set()
modified_columns = set()
for index, value in zip(indexes, values):
row = index.row()
modified_rows.append(row)
modified_rows.add(row)
column = index.column()
modified_columns.append(column)
modified_columns.add(column)
if column == 0:
self._value.indexes[row] = value
else:
self._value.values[row] = value
left_top = self.index(min(modified_rows), min(modified_columns))
right_bottom = self.index(max(modified_rows), max(modified_columns))
self.dataChanged.emit(left_top, right_bottom, [Qt.ItemDataRole.EditRole])
self.dataChanged.emit(left_top, right_bottom, [Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole])

@Slot(bool, name="set_ignore_year")
def set_ignore_year(self, ignore_year):
Expand Down
4 changes: 2 additions & 2 deletions spinetoolbox/ui/datetime_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
################################################################################
## Form generated from reading UI file 'datetime_editor.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
## Created by: Qt User Interface Compiler version 6.6.3
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
Expand Down Expand Up @@ -72,6 +72,6 @@ def retranslateUi(self, DatetimeEditor):
DatetimeEditor.setWindowTitle(QCoreApplication.translate("DatetimeEditor", u"Form", None))
self.datetime_edit_label.setText(QCoreApplication.translate("DatetimeEditor", u"Datetime", None))
self.datetime_edit.setDisplayFormat(QCoreApplication.translate("DatetimeEditor", u"yyyy-MM-ddTHH:mm:ss", None))
self.format_label.setText(QCoreApplication.translate("DatetimeEditor", u"Format: YYYY--MM-DDThh:mm:ss", None))
self.format_label.setText(QCoreApplication.translate("DatetimeEditor", u"Format: YYYY-MM-DDThh:mm:ss", None))
# retranslateUi

3 changes: 2 additions & 1 deletion spinetoolbox/ui/datetime_editor.ui
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<!--
######################################################################################################################
# Copyright (C) 2017-2022 Spine project consortium
# Copyright Spine Toolbox contributors
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and\/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
Expand Down Expand Up @@ -50,7 +51,7 @@
<item>
<widget class="QLabel" name="format_label">
<property name="text">
<string>Format: YYYY--MM-DDThh:mm:ss</string>
<string>Format: YYYY-MM-DDThh:mm:ss</string>
</property>
</widget>
</item>
Expand Down
Loading

0 comments on commit f593c2c

Please sign in to comment.