Ready-to-use widgets¶
As a complement to the guidata.dataset
module which focus on automatic
GUI generation for data sets editing and display, the guidata.widgets
module provides a set of ready-to-use widgets for building interactive GUIs.
Note
Most of the widgets originally come from the Spyder project (Copyright © Spyder Project Contributors, MIT-licensed). They were adapted to be used outside of the Spyder IDE and to be compatible with guidata internals.
Python console¶
from guidata.configtools import get_icon
from guidata.env import execenv
from guidata.qthelpers import qt_app_context
from guidata.widgets.console import Console
def test_console():
"""Test Console widget."""
with qt_app_context(exec_loop=True):
widget = Console(debug=False, multithreaded=True)
widget.resize(800, 600)
widget.setWindowTitle("Console")
widget.setWindowIcon(get_icon("guidata.svg"))
widget.show()
execenv.print("OK")
if __name__ == "__main__":
test_console()
Code editor¶
from guidata.configtools import get_icon
from guidata.env import execenv
from guidata.qthelpers import qt_app_context
from guidata.widgets import codeeditor
def test_codeeditor():
"""Test Code editor."""
with qt_app_context(exec_loop=True):
widget = codeeditor.CodeEditor(language="python")
widget.set_text_from_file(codeeditor.__file__)
widget.resize(800, 600)
widget.setWindowTitle("Code editor")
widget.setWindowIcon(get_icon("guidata.svg"))
widget.show()
execenv.print("OK")
if __name__ == "__main__":
test_codeeditor()
Array editor¶
import numpy as np
from guidata.env import execenv
from guidata.qthelpers import exec_dialog, qt_app_context
from guidata.widgets.arrayeditor import ArrayEditor
def launch_arrayeditor(data, title="", xlabels=None, ylabels=None, variable_size=False):
"""Helper routine to launch an arrayeditor and return its result"""
dlg = ArrayEditor()
dlg.setup_and_check(
data, title, xlabels=xlabels, ylabels=ylabels, variable_size=variable_size
)
exec_dialog(dlg)
return dlg.get_value()
def test_arrayeditor():
"""Test array editor for all supported data types"""
with qt_app_context():
# Variable size version
for title, data in (
("string array", np.array(["kjrekrjkejr"])),
(
"masked array",
np.ma.array([[1, 0], [1, 0]], mask=[[True, False], [False, False]]),
),
("int array", np.array([1, 2, 3], dtype="int8")),
):
launch_arrayeditor(data, "[Variable size] " + title, variable_size=True)
for title, data in (
("string array", np.array(["kjrekrjkejr"])),
("unicode array", np.array(["ñññéáíó"])),
(
"masked array",
np.ma.array([[1, 0], [1, 0]], mask=[[True, False], [False, False]]),
),
(
"record array",
np.zeros(
(2, 2),
{
"names": ("red", "green", "blue"),
"formats": (np.float32, np.float32, np.float32),
},
),
),
(
"record array with titles",
np.array(
[(0, 0.0), (0, 0.0), (0, 0.0)],
dtype=[(("title 1", "x"), "|i1"), (("title 2", "y"), ">f4")],
),
),
("bool array", np.array([True, False, True])),
("int array", np.array([1, 2, 3], dtype="int8")),
("float16 array", np.zeros((5, 5), dtype=np.float16)),
):
launch_arrayeditor(data, title)
for title, data, xlabels, ylabels in (
("float array", np.random.rand(5, 5), ["a", "b", "c", "d", "e"], None),
(
"complex array",
np.round(np.random.rand(5, 5) * 10)
+ np.round(np.random.rand(5, 5) * 10) * 1j,
np.linspace(-12, 12, 5),
np.linspace(-12, 12, 5),
),
):
launch_arrayeditor(data, title, xlabels, ylabels)
arr = np.zeros((3, 3, 4))
arr[0, 0, 0] = 1
arr[0, 0, 1] = 2
arr[0, 0, 2] = 3
launch_arrayeditor(arr, "3D array")
execenv.print("OK")
if __name__ == "__main__":
test_arrayeditor()
Collection editor¶
import datetime
import numpy as np
from guidata.env import execenv
from guidata.qthelpers import qt_app_context
from guidata.widgets.collectionseditor import CollectionsEditor
try:
from PIL import Image as PILImage
except ImportError:
# PIL is not installed
PILImage = None
def get_test_data():
"""Create test data."""
testdict = {"d": 1, "a": np.random.rand(10, 10), "b": [1, 2]}
testdate = datetime.date(1945, 5, 8)
test_timedelta = datetime.timedelta(days=-1, minutes=42, seconds=13)
try:
import pandas as pd
except (ModuleNotFoundError, ImportError):
test_timestamp = None
test_pd_td = None
test_dtindex = None
test_series = None
test_df = None
else:
test_timestamp = pd.Timestamp("1945-05-08T23:01:00.12345")
test_pd_td = pd.Timedelta(days=2193, hours=12)
test_dtindex = pd.date_range(start="1939-09-01T", end="1939-10-06", freq="12h")
test_series = pd.Series({"series_name": [0, 1, 2, 3, 4, 5]})
test_df = pd.DataFrame(
{
"string_col": ["a", "b", "c", "d"],
"int_col": [0, 1, 2, 3],
"float_col": [1.1, 2.2, 3.3, 4.4],
"bool_col": [True, False, False, True],
}
)
class Foobar:
""" """
def __init__(self):
self.text = "toto"
self.testdict = testdict
self.testdate = testdate
foobar = Foobar()
test_data = {
"object": foobar,
"module": np,
"str": "kjkj kj k j j kj k jkj",
"unicode": "éù",
"list": [1, 3, [sorted, 5, 6], "kjkj", None],
"tuple": ([1, testdate, testdict, test_timedelta], "kjkj", None),
"dict": testdict,
"float": 1.2233,
"int": 223,
"bool": True,
"array": np.random.rand(10, 10).astype(np.int64),
"masked_array": np.ma.array(
[[1, 0], [1, 0]], mask=[[True, False], [False, False]]
),
"1D-array": np.linspace(-10, 10).astype(np.float16),
"3D-array": np.random.randint(2, size=(5, 5, 5)).astype(np.bool_),
"empty_array": np.array([]),
"date": testdate,
"datetime": datetime.datetime(1945, 5, 8, 23, 1, 0, int(1.5e5)),
"timedelta": test_timedelta,
"complex": 2 + 1j,
"complex64": np.complex64(2 + 1j),
"complex128": np.complex128(9j),
"int8_scalar": np.int8(8),
"int16_scalar": np.int16(16),
"int32_scalar": np.int32(32),
"int64_scalar": np.int64(64),
"float16_scalar": np.float16(16),
"float32_scalar": np.float32(32),
"float64_scalar": np.float64(64),
"bool_scalar": bool,
"bool__scalar": np.bool_(8),
"timestamp": test_timestamp,
"timedelta_pd": test_pd_td,
"datetimeindex": test_dtindex,
"series": test_series,
"ddataframe": test_df,
"None": None,
"unsupported1": np.arccos,
"unsupported2": np.cast,
# Test for Issue #3518
"big_struct_array": np.zeros(
1000, dtype=[("ID", "f8"), ("param1", "f8", 5000)]
),
}
if PILImage is not None:
image = PILImage.fromarray(np.random.randint(256, size=(100, 100)), mode="P")
test_data["image"] = image
return test_data
def test_collectionseditor():
"""Test Collections editor."""
with qt_app_context(exec_loop=True):
dialog = CollectionsEditor()
dialog.setup(get_test_data())
dialog.show()
execenv.print("OK")
if __name__ == "__main__":
test_collectionseditor()
Dataframe editor¶
import numpy as np
import pytest
try:
import pandas as pd
import pandas.testing as pdt
from guidata.widgets.dataframeeditor import DataFrameEditor
except ImportError:
# pandas is not installed
pd = pdt = DataFrameEditor = None
from guidata.env import execenv
from guidata.qthelpers import exec_dialog, qt_app_context
@pytest.mark.skipif(pd is None, reason="pandas is not installed")
def test_dataframeeditor():
"""DataFrame editor test"""
def test_edit(data, title="", parent=None):
"""Test subroutine"""
dlg = DataFrameEditor(parent=parent)
if dlg.setup_and_check(data, title=title):
exec_dialog(dlg)
return dlg.get_value()
else:
import sys
sys.exit(1)
with qt_app_context():
df1 = pd.DataFrame(
[
[True, "bool"],
[1 + 1j, "complex"],
["test", "string"],
[1.11, "float"],
[1, "int"],
[np.random.rand(3, 3), "Unkown type"],
["Large value", 100],
["áéí", "unicode"],
],
index=["a", "b", np.nan, np.nan, np.nan, "c", "Test global max", "d"],
columns=[np.nan, "Type"],
)
out = test_edit(df1)
pdt.assert_frame_equal(df1, out)
result = pd.Series([True, "bool"], index=[np.nan, "Type"], name="a")
out = test_edit(df1.iloc[0])
pdt.assert_series_equal(result, out)
df1 = pd.DataFrame(np.random.rand(100100, 10))
out = test_edit(df1)
pdt.assert_frame_equal(out, df1)
series = pd.Series(np.arange(10), name=0)
out = test_edit(series)
pdt.assert_series_equal(series, out)
execenv.print("OK")
if __name__ == "__main__":
test_dataframeeditor()
Import wizard¶
import pytest
from guidata.env import execenv
from guidata.qthelpers import exec_dialog, qt_app_context
from guidata.widgets.importwizard import ImportWizard
@pytest.fixture()
def text():
"""Return text to test"""
return "17/11/1976\t1.34\n14/05/09\t3.14"
def test_importwizard(text):
"""Test"""
with qt_app_context():
dialog = ImportWizard(None, text)
if exec_dialog(dialog):
execenv.print(dialog.get_data())
execenv.print("OK")
if __name__ == "__main__":
test_importwizard("17/11/1976\t1.34\n14/05/09\t3.14")