Krita Source Code Documentation
Loading...
Searching...
No Matches
KisWdgSeExpr Class Reference

#include <kis_wdg_seexpr.h>

+ Inheritance diagram for KisWdgSeExpr:

Public Member Functions

KisPropertiesConfigurationSP configuration () const override
 
 KisWdgSeExpr (QWidget *parent=0)
 
void setConfiguration (const KisPropertiesConfigurationSP) override
 
const Ui_WdgSeExpr * widget () const
 
 ~KisWdgSeExpr () override
 
- Public Member Functions inherited from KisConfigWidget
virtual KoCanvasResourcesInterfaceSP canvasResourcesInterface () const
 
virtual void setCanvasResourcesInterface (KoCanvasResourcesInterfaceSP canvasResourcesInterface)
 
virtual void setView (KisViewManager *view)
 
 ~KisConfigWidget () override
 

Private Slots

void isValid ()
 
void slotHideCheckboxes ()
 
void slotReloadPresetClicked ()
 
void slotRenamePresetActivated ()
 
void slotRenamePresetDeactivated ()
 
void slotResourceSaved (KoResourceSP resource)
 
void slotResourceSelected (KoResourceSP resource)
 
void slotSaveBrushPreset ()
 
void slotSaveNewBrushPreset ()
 
void slotSaveRenameCurrentPreset ()
 
void slotUpdatePresetSettings ()
 

Private Member Functions

void togglePresetRenameUIActive (bool isRenaming)
 

Private Attributes

KisSeExprScriptSP m_currentPreset
 
bool m_isCreatingPresetFromScratch
 
KisWdgSeExprPresetsSavem_saveDialog
 
Ui_WdgSeExpr * m_widget
 
KisSignalCompressor updateCompressor
 

Additional Inherited Members

- Signals inherited from KisConfigWidget
void sigConfigurationItemChanged ()
 
void sigConfigurationUpdated ()
 
void sigDropLockedConfig (KisPropertiesConfigurationSP p)
 
void sigSaveLockedConfig (KisPropertiesConfigurationSP p)
 
- Protected Member Functions inherited from KisConfigWidget
 KisConfigWidget (QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags(), int delay=200)
 

Detailed Description

Definition at line 20 of file kis_wdg_seexpr.h.

Constructor & Destructor Documentation

◆ KisWdgSeExpr()

KisWdgSeExpr::KisWdgSeExpr ( QWidget * parent = 0)

Definition at line 31 of file kis_wdg_seexpr.cpp.

32 : KisConfigWidget(parent)
34 , m_currentPreset(new KisSeExprScript(i18n("Untitled")))
37{
38 m_widget = new Ui_WdgSeExpr();
39 m_widget->setupUi(this);
40 m_widget->txtEditor->setControlCollectionWidget(m_widget->wdgControls);
41
42 m_widget->renameBrushPresetButton->setIcon(KisIconUtils::loadIcon("document-edit"));
43
44 m_widget->reloadPresetButton->setIcon(KisIconUtils::loadIcon("reload-preset-16"));
45 m_widget->reloadPresetButton->setToolTip(i18n("Reload the preset"));
46 m_widget->dirtyPresetIndicatorButton->setIcon(KisIconUtils::loadIcon("warning"));
47 m_widget->dirtyPresetIndicatorButton->setToolTip(i18n("The settings for this preset have changed from their default."));
48
49 KisDialogStateSaver::restoreState(m_widget->txtEditor, "krita/generators/seexpr");
50 // Manually restore SeExpr state. KisDialogStateSaver uses setPlainText, not text itself
51 m_widget->txtEditor->setExpr(m_widget->txtEditor->exprTe->toPlainText());
52
53 m_widget->txtEditor->registerExtraVariable("$u", i18nc("SeExpr variable", "Normalized X axis coordinate of the image from its top-left corner"));
54 m_widget->txtEditor->registerExtraVariable("$v", i18nc("SeExpr variable", "Normalized Y axis coordinate of the image from its top-left corner"));
55 m_widget->txtEditor->registerExtraVariable("$w", i18nc("SeExpr variable", "Image width"));
56 m_widget->txtEditor->registerExtraVariable("$h", i18nc("SeExpr variable", "Image height"));
57
58 m_widget->txtEditor->updateCompleter();
59
60 m_widget->txtEditor->exprTe->setFont(QFontDatabase().systemFont(QFontDatabase::FixedFont));
61 const QFontMetricsF fntTe(m_widget->txtEditor->exprTe->fontMetrics());
62 m_widget->txtEditor->exprTe->setTabStopDistance(fntTe.horizontalAdvance(" "));
63
64 connect(m_widget->scriptSelectorWidget, SIGNAL(resourceSelected(KoResourceSP)), this, SLOT(slotResourceSelected(KoResourceSP)));
65 connect(m_saveDialog, SIGNAL(resourceSelected(KoResourceSP)), this, SLOT(slotResourceSaved(KoResourceSP)));
66
67 connect(m_widget->renameBrushPresetButton, SIGNAL(clicked(bool)),
68 this, SLOT(slotRenamePresetActivated()));
69 connect(m_widget->cancelBrushNameUpdateButton, SIGNAL(clicked(bool)),
70 this, SLOT(slotRenamePresetDeactivated()));
71 connect(m_widget->updateBrushNameButton, SIGNAL(clicked(bool)),
72 this, SLOT(slotSaveRenameCurrentPreset()));
73 connect(m_widget->renameBrushNameTextField, SIGNAL(returnPressed()),
74 this, SLOT(slotSaveRenameCurrentPreset()));
75
76 connect(m_widget->saveBrushPresetButton, SIGNAL(clicked()),
77 this, SLOT(slotSaveBrushPreset()));
78 connect(m_widget->saveNewBrushPresetButton, SIGNAL(clicked()),
79 this, SLOT(slotSaveNewBrushPreset()));
80
81 connect(m_widget->reloadPresetButton, SIGNAL(clicked()),
82 this, SLOT(slotReloadPresetClicked()));
83
84 connect(m_widget->txtEditor, SIGNAL(apply()),
85 &updateCompressor, SLOT(start()));
86 connect(m_widget->txtEditor, SIGNAL(preview()),
87 &updateCompressor, SLOT(start()));
88 connect(m_widget->txtEditor, &ExprEditor::preview, this, &KisWdgSeExpr::slotHideCheckboxes); // HACK: hide disney checkboxes
89
90 connect(&updateCompressor, SIGNAL(timeout()), this, SLOT(isValid()));
91
92 togglePresetRenameUIActive(false); // reset the UI state of renaming a preset if we are changing presets
93 slotUpdatePresetSettings(); // disable everything until a preset is selected
94
95 m_widget->splitter->restoreState(KisConfig(true).readEntry("seExpr/splitLayoutState", QByteArray())); // restore splitter state
96 m_widget->tabWidget->setCurrentIndex(KisConfig(true).readEntry("seExpr/selectedTab", -1)); // save currently selected tab
97}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisConfigWidget(QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags(), int delay=200)
void slotHideCheckboxes()
KisWdgSeExprPresetsSave * m_saveDialog
void slotResourceSelected(KoResourceSP resource)
KisSignalCompressor updateCompressor
KisSeExprScriptSP m_currentPreset
void slotReloadPresetClicked()
void slotSaveNewBrushPreset()
void slotSaveRenameCurrentPreset()
void slotRenamePresetActivated()
void slotUpdatePresetSettings()
void slotSaveBrushPreset()
bool m_isCreatingPresetFromScratch
Ui_WdgSeExpr * m_widget
void slotResourceSaved(KoResourceSP resource)
void togglePresetRenameUIActive(bool isRenaming)
void slotRenamePresetDeactivated()
KRITAWIDGETUTILS_EXPORT void restoreState(QWidget *parent, const QString &dialogName, const QMap< QString, QVariant > &defaults=QMap< QString, QVariant >())
restoreState restores the state of the dialog
QIcon loadIcon(const QString &name)

References connect(), isValid(), KisIconUtils::loadIcon(), m_saveDialog, m_widget, KisDialogStateSaver::restoreState(), slotHideCheckboxes(), slotReloadPresetClicked(), slotRenamePresetActivated(), slotRenamePresetDeactivated(), slotResourceSaved(), slotResourceSelected(), slotSaveBrushPreset(), slotSaveNewBrushPreset(), slotSaveRenameCurrentPreset(), slotUpdatePresetSettings(), togglePresetRenameUIActive(), and updateCompressor.

◆ ~KisWdgSeExpr()

KisWdgSeExpr::~KisWdgSeExpr ( )
override

Definition at line 99 of file kis_wdg_seexpr.cpp.

100{
101 KisDialogStateSaver::saveState(m_widget->txtEditor, "krita/generators/seexpr");
102 KisConfig(false).writeEntry("seExpr/splitLayoutState", m_widget->splitter->saveState()); // save splitter state
103 KisConfig(false).writeEntry("seExpr/selectedTab", m_widget->tabWidget->currentIndex()); // save currently selected tab
104
105 delete m_saveDialog;
106 delete m_widget;
107}
void writeEntry(const QString &name, const T &value)
Definition kis_config.h:779
KRITAWIDGETUTILS_EXPORT void saveState(QWidget *parent, const QString &dialogName)
saveState saves the state for the specified widgets

References m_saveDialog, m_widget, KisDialogStateSaver::saveState(), and KisConfig::writeEntry().

Member Function Documentation

◆ configuration()

KisPropertiesConfigurationSP KisWdgSeExpr::configuration ( ) const
overridevirtual
Returns
the configuration

Implements KisConfigWidget.

Definition at line 130 of file kis_wdg_seexpr.cpp.

131{
133
134 if (m_widget->scriptSelectorWidget->currentResource()) {
135 QVariant v;
136 v.setValue(m_widget->scriptSelectorWidget->currentResource()->name());
137 config->setProperty("pattern", v);
138 }
139 config->setProperty("script", QVariant(m_widget->txtEditor->getExpr()));
140
141 return config;
142}
qreal v
static KisResourcesInterfaceSP instance()

References KisGlobalResourcesInterface::instance(), m_widget, and v.

◆ isValid

void KisWdgSeExpr::isValid ( )
privateslot

Definition at line 328 of file kis_wdg_seexpr.cpp.

329{
330 QString script = m_widget->txtEditor->getExpr();
331 SeExprExpressionContext expression(script);
332
333 expression.setDesiredReturnType(KSeExpr::ExprType().FP(3));
334
335 expression.m_vars["u"] = new SeExprVariable();
336 expression.m_vars["v"] = new SeExprVariable();
337 expression.m_vars["w"] = new SeExprVariable();
338 expression.m_vars["h"] = new SeExprVariable();
339
340 m_widget->txtEditor->clearErrors();
341
342 if (!expression.isValid()) {
343 const auto &errors = expression.getErrors();
344
345 for (const auto &occurrence : errors) {
346 QString message = ErrorMessages::message(occurrence.error);
347 for (const auto &arg : occurrence.ids) {
348 message = message.arg(QString::fromStdString(arg));
349 }
350 m_widget->txtEditor->addError(occurrence.startPos, occurrence.endPos, message);
351 }
352
353 m_widget->saveBrushPresetButton->setEnabled(false);
354 m_widget->saveNewBrushPresetButton->setEnabled(false);
355 }
356 // Should not happen now, but I've left it for completeness's sake
357 else if (!expression.returnType().isFP(3)) {
358 QString type = QString::fromStdString(expression.returnType().toString());
359 m_widget->txtEditor->addError(1, 1, tr2i18n("Expected this script to output color, got '%1'").arg(type));
360
361 m_widget->saveBrushPresetButton->setEnabled(false);
362 m_widget->saveNewBrushPresetButton->setEnabled(false);
363 } else {
364 m_widget->txtEditor->clearErrors();
366
367 if (m_currentPreset->script() != m_widget->txtEditor->getExpr()) {
368 m_currentPreset->setScript(m_widget->txtEditor->getExpr());
369 m_currentPreset->setDirty(true);
370 }
371
373
374 // Override preset settings with the following
376 m_widget->saveNewBrushPresetButton->setEnabled(true);
377 }
378 }
379}
void sigConfigurationItemChanged()

References m_currentPreset, m_isCreatingPresetFromScratch, SeExprExpressionContext::m_vars, m_widget, KisConfigWidget::sigConfigurationItemChanged(), and slotUpdatePresetSettings().

◆ setConfiguration()

void KisWdgSeExpr::setConfiguration ( const KisPropertiesConfigurationSP config)
overridevirtual
Parameters
configthe configuration for this configuration widget.

Implements KisConfigWidget.

Definition at line 114 of file kis_wdg_seexpr.cpp.

115{
116 auto rserver = KoResourceServerProvider::instance()->seExprScriptServer();
117 auto name = config->getString("seexpr", "Disney_noisecolor2");
118 auto pattern = rserver->resource("", "", name);
119 if (pattern) {
120 m_widget->scriptSelectorWidget->setCurrentScript(pattern);
121 }
122
123 QString script = config->getString("script");
124
125 if (!script.isNull()) {
126 m_widget->txtEditor->setExpr(script, true);
127 }
128}
const char * name(StandardAction id)
static KoResourceServerProvider * instance()

References KoResourceServerProvider::instance(), and m_widget.

◆ slotHideCheckboxes

void KisWdgSeExpr::slotHideCheckboxes ( )
privateslot

Definition at line 318 of file kis_wdg_seexpr.cpp.

319{
320 for (auto controls : m_widget->wdgControls->findChildren<ExprControl *>()) {
321 for (auto wdg : controls->findChildren<QCheckBox *>(QString(), Qt::FindDirectChildrenOnly)) {
322 wdg->setCheckState(Qt::Unchecked);
323 wdg->setVisible(false);
324 }
325 }
326}

References m_widget.

◆ slotReloadPresetClicked

void KisWdgSeExpr::slotReloadPresetClicked ( )
privateslot

Definition at line 300 of file kis_wdg_seexpr.cpp.

301{
302 KisSignalsBlocker blocker(this);
303
305 const bool success = model.reloadResource(m_currentPreset);
306
307 KIS_SAFE_ASSERT_RECOVER_NOOP(success && "couldn't reload preset");
308
309 warnPlugins << "resourceSelected: preset" << m_currentPreset
310 << (m_currentPreset ? QString("%1").arg(m_currentPreset->valid()) : "");
311
312 KIS_ASSERT(!m_currentPreset->isDirty());
313
314 // refresh and select our freshly renamed resource
316}
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
#define warnPlugins
Definition kis_debug.h:93
const QString SeExprScripts

References KIS_ASSERT, KIS_SAFE_ASSERT_RECOVER_NOOP, m_currentPreset, KisResourceModel::reloadResource(), ResourceType::SeExprScripts, slotResourceSelected(), and warnPlugins.

◆ slotRenamePresetActivated

void KisWdgSeExpr::slotRenamePresetActivated ( )
privateslot

Definition at line 178 of file kis_wdg_seexpr.cpp.

179{
181}

References togglePresetRenameUIActive().

◆ slotRenamePresetDeactivated

void KisWdgSeExpr::slotRenamePresetDeactivated ( )
privateslot

Definition at line 183 of file kis_wdg_seexpr.cpp.

184{
186}

References togglePresetRenameUIActive().

◆ slotResourceSaved

void KisWdgSeExpr::slotResourceSaved ( KoResourceSP resource)
privateslot

Definition at line 144 of file kis_wdg_seexpr.cpp.

145{
146 if (resource) {
147 m_widget->scriptSelectorWidget->setCurrentScript(resource);
148 slotResourceSelected(resource);
149 }
150}

References m_widget, and slotResourceSelected().

◆ slotResourceSelected

void KisWdgSeExpr::slotResourceSelected ( KoResourceSP resource)
privateslot

Definition at line 152 of file kis_wdg_seexpr.cpp.

153{
154 KisSeExprScriptSP preset = resource.dynamicCast<KisSeExprScript>();
155 if (preset) {
156 m_currentPreset = preset;
157
159
160 m_widget->txtEditor->setExpr(m_currentPreset->script(), true);
161
162 QString formattedBrushName = m_currentPreset->name().replace("_", " ");
163 m_widget->currentBrushNameLabel->setText(formattedBrushName);
164 m_widget->renameBrushNameTextField->setText(formattedBrushName);
165 // get the preset image and pop it into the thumbnail area on the top of the brush editor
166 QSize thumbSize = QSize(55, 55)*devicePixelRatioF();
167 QPixmap thumbnail = QPixmap::fromImage(m_currentPreset->image().scaled(thumbSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
168 thumbnail.setDevicePixelRatio(devicePixelRatioF());
169 m_widget->presetThumbnailicon->setPixmap(thumbnail);
170
171 togglePresetRenameUIActive(false); // reset the UI state of renaming a brush if we are changing brush presets
172 slotUpdatePresetSettings(); // check to see if the dirty preset icon needs to be shown
173
175 }
176}

References m_currentPreset, m_isCreatingPresetFromScratch, m_widget, slotUpdatePresetSettings(), KisSignalCompressor::start(), togglePresetRenameUIActive(), and updateCompressor.

◆ slotSaveBrushPreset

void KisWdgSeExpr::slotSaveBrushPreset ( )
privateslot

Definition at line 278 of file kis_wdg_seexpr.cpp.

279{
280 KisFilterConfigurationSP currentConfiguration = static_cast<KisFilterConfiguration *>(configuration().data());
281
282 m_saveDialog->useNewPresetDialog(false); // this mostly just makes sure we keep the existing brush preset name when saving
284 m_saveDialog->setCurrentRenderConfiguration(currentConfiguration);
285 m_saveDialog->loadExistingThumbnail(); // This makes sure we use the existing preset icon when updating the existing brush preset
286 m_saveDialog->showDialog(); // apply tiar's suggestion and let the user decide
287}
void setCurrentPreset(KisSeExprScriptSP resource)
void setCurrentRenderConfiguration(KisFilterConfigurationSP config)
void useNewPresetDialog(bool show)
determines if we should show the save as dialog (true) or save in the background (false)
KisPropertiesConfigurationSP configuration() const override

References configuration(), KisSharedPtr< T >::data(), KisWdgSeExprPresetsSave::loadExistingThumbnail(), m_currentPreset, m_saveDialog, KisWdgSeExprPresetsSave::setCurrentPreset(), KisWdgSeExprPresetsSave::setCurrentRenderConfiguration(), KisWdgSeExprPresetsSave::showDialog(), and KisWdgSeExprPresetsSave::useNewPresetDialog().

◆ slotSaveNewBrushPreset

◆ slotSaveRenameCurrentPreset

void KisWdgSeExpr::slotSaveRenameCurrentPreset ( )
privateslot

Definition at line 204 of file kis_wdg_seexpr.cpp.

205{
207
208 // if you are renaming a brush, that is different than updating the settings
209 // make sure we are in a clean state before renaming. This logic might change,
210 // but that is what we are going with for now
211 const auto prevScript = m_currentPreset->script();
212 bool isDirty = m_currentPreset->isDirty();
213
214 // this returns the UI to its original state after saving
216 slotUpdatePresetSettings(); // update visibility of dirty preset and icon
217
218 // in case the preset is dirty, we need an id to get the actual non-dirty preset to save just the name change
219 // into the database
220 int currentPresetResourceId = m_currentPreset->resourceId();
221
222 QString renamedPresetName = m_widget->renameBrushNameTextField->text();
223
224 // If the id < 0, this is a new preset that hasn't been added to the storage and the database yet.
225 if (currentPresetResourceId < 0) {
226 m_currentPreset->setName(renamedPresetName);
227 slotUpdatePresetSettings(); // update visibility of dirty preset and icon
228 return;
229 }
230
232
233 // create a new brush preset with the name specified and add to resource provider
235 KoResourceSP properCleanResource = model.resourceForId(currentPresetResourceId);
236 const bool success = KisResourceUserOperations::renameResourceWithUserInput(this, properCleanResource, renamedPresetName);
237
238 if (isDirty) {
239 properCleanResource.dynamicCast<KisSeExprScript>()->setScript(prevScript);
240 properCleanResource.dynamicCast<KisSeExprScript>()->setDirty(isDirty);
241 }
242
243 // refresh and select our freshly renamed resource
244 if (success) slotResourceSelected(properCleanResource);
245
246
247 slotUpdatePresetSettings(); // update visibility of dirty preset and icon
248}
static bool renameResourceWithUserInput(QWidget *widgetParent, KoResourceSP resource, QString resourceName)
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75

References KIS_ASSERT_RECOVER_RETURN, m_currentPreset, m_widget, KisResourceUserOperations::renameResourceWithUserInput(), KisResourceModel::resourceForId(), ResourceType::SeExprScripts, slotReloadPresetClicked(), slotResourceSelected(), slotUpdatePresetSettings(), and togglePresetRenameUIActive().

◆ slotUpdatePresetSettings

void KisWdgSeExpr::slotUpdatePresetSettings ( )
privateslot

Definition at line 250 of file kis_wdg_seexpr.cpp.

251{
252 // hide options on UI if we are creating a brush preset from scratch to prevent confusion
254 m_widget->presetThumbnailicon->setVisible(false);
255 m_widget->dirtyPresetIndicatorButton->setVisible(false);
256 m_widget->reloadPresetButton->setVisible(false);
257 m_widget->saveBrushPresetButton->setVisible(false);
258 m_widget->saveNewBrushPresetButton->setEnabled(false);
259 m_widget->renameBrushPresetButton->setVisible(false);
260 } else {
261 // In SeExpr's case, there is never a default preset -- amyspark
262 if (!m_currentPreset) {
263 return;
264 }
265
266 bool isPresetDirty = m_currentPreset->isDirty();
267
268 m_widget->presetThumbnailicon->setVisible(true);
269 // don't need to reload or overwrite a clean preset
270 m_widget->dirtyPresetIndicatorButton->setVisible(isPresetDirty);
271 m_widget->reloadPresetButton->setVisible(isPresetDirty);
272 m_widget->saveBrushPresetButton->setEnabled(isPresetDirty);
273 m_widget->saveNewBrushPresetButton->setEnabled(true);
274 m_widget->renameBrushPresetButton->setVisible(true);
275 }
276}

References m_currentPreset, m_isCreatingPresetFromScratch, and m_widget.

◆ togglePresetRenameUIActive()

void KisWdgSeExpr::togglePresetRenameUIActive ( bool isRenaming)
private

Definition at line 188 of file kis_wdg_seexpr.cpp.

189{
190 // This function doesn't really do anything except get the UI in a state to rename a brush preset
191 m_widget->renameBrushNameTextField->setVisible(isRenaming);
192 m_widget->updateBrushNameButton->setVisible(isRenaming);
193 m_widget->cancelBrushNameUpdateButton->setVisible(isRenaming);
194
195 // hide these below areas while renaming
196 m_widget->currentBrushNameLabel->setVisible(!isRenaming);
197 m_widget->renameBrushPresetButton->setVisible(!isRenaming);
198 m_widget->saveBrushPresetButton->setEnabled(!isRenaming);
199 m_widget->saveBrushPresetButton->setVisible(!isRenaming);
200 m_widget->saveNewBrushPresetButton->setEnabled(!isRenaming);
201 m_widget->saveNewBrushPresetButton->setVisible(!isRenaming);
202}

References m_widget.

◆ widget()

const Ui_WdgSeExpr * KisWdgSeExpr::widget ( ) const
inline

Definition at line 109 of file kis_wdg_seexpr.cpp.

110{
111 return m_widget;
112}

References m_widget.

Member Data Documentation

◆ m_currentPreset

KisSeExprScriptSP KisWdgSeExpr::m_currentPreset
private

Definition at line 48 of file kis_wdg_seexpr.h.

◆ m_isCreatingPresetFromScratch

bool KisWdgSeExpr::m_isCreatingPresetFromScratch
private

Definition at line 51 of file kis_wdg_seexpr.h.

◆ m_saveDialog

KisWdgSeExprPresetsSave* KisWdgSeExpr::m_saveDialog
private

Definition at line 49 of file kis_wdg_seexpr.h.

◆ m_widget

Ui_WdgSeExpr* KisWdgSeExpr::m_widget
private

Definition at line 46 of file kis_wdg_seexpr.h.

◆ updateCompressor

KisSignalCompressor KisWdgSeExpr::updateCompressor
private

Definition at line 47 of file kis_wdg_seexpr.h.


The documentation for this class was generated from the following files: