pygpt-net 2.7.0__py3-none-any.whl → 2.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. pygpt_net/CHANGELOG.txt +8 -0
  2. pygpt_net/__init__.py +1 -1
  3. pygpt_net/controller/ctx/ctx.py +4 -1
  4. pygpt_net/controller/painter/common.py +43 -11
  5. pygpt_net/core/filesystem/filesystem.py +70 -0
  6. pygpt_net/core/filesystem/packer.py +161 -1
  7. pygpt_net/core/image/image.py +2 -2
  8. pygpt_net/core/video/video.py +2 -3
  9. pygpt_net/data/config/config.json +2 -2
  10. pygpt_net/data/config/models.json +2 -2
  11. pygpt_net/data/css/style.dark.css +12 -5
  12. pygpt_net/data/css/style.light.css +12 -4
  13. pygpt_net/data/locale/locale.de.ini +2 -0
  14. pygpt_net/data/locale/locale.en.ini +2 -0
  15. pygpt_net/data/locale/locale.es.ini +2 -0
  16. pygpt_net/data/locale/locale.fr.ini +2 -0
  17. pygpt_net/data/locale/locale.it.ini +2 -0
  18. pygpt_net/data/locale/locale.pl.ini +3 -1
  19. pygpt_net/data/locale/locale.uk.ini +2 -0
  20. pygpt_net/data/locale/locale.zh.ini +2 -0
  21. pygpt_net/provider/core/config/patch.py +8 -0
  22. pygpt_net/ui/dialog/preset.py +1 -0
  23. pygpt_net/ui/layout/toolbox/image.py +2 -1
  24. pygpt_net/ui/layout/toolbox/indexes.py +2 -0
  25. pygpt_net/ui/layout/toolbox/video.py +5 -1
  26. pygpt_net/ui/widget/draw/painter.py +238 -51
  27. pygpt_net/ui/widget/filesystem/explorer.py +82 -0
  28. pygpt_net/ui/widget/option/combo.py +177 -13
  29. {pygpt_net-2.7.0.dist-info → pygpt_net-2.7.1.dist-info}/METADATA +10 -2
  30. {pygpt_net-2.7.0.dist-info → pygpt_net-2.7.1.dist-info}/RECORD +33 -33
  31. {pygpt_net-2.7.0.dist-info → pygpt_net-2.7.1.dist-info}/LICENSE +0 -0
  32. {pygpt_net-2.7.0.dist-info → pygpt_net-2.7.1.dist-info}/WHEEL +0 -0
  33. {pygpt_net-2.7.0.dist-info → pygpt_net-2.7.1.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,11 @@
1
+ 2.7.1 (2025-12-28)
2
+
3
+ - Improved UI elements.
4
+ - Optimized Painter rendering and redraw functions.
5
+ - Added Pack/Unpack feature to File Explorer.
6
+ - Fixed: image restoration in Painter.
7
+ - Fixed: tab title updating upon context deletion.
8
+
1
9
  2.7.0 (2025-12-28)
2
10
 
3
11
  - Added multi-select functionality using CTRL or SHIFT and batch actions to the context list, preset list, attachments list, and other list-based widgets.
pygpt_net/__init__.py CHANGED
@@ -13,7 +13,7 @@ __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.7.0"
16
+ __version__ = "2.7.1"
17
17
  __build__ = "2025-12-28"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
@@ -622,6 +622,7 @@ class Ctx:
622
622
  )
623
623
  return
624
624
  updated = False
625
+ updated_current = False
625
626
  ids = id if isinstance(id, list) else [id]
626
627
  for id in ids:
627
628
  try:
@@ -633,6 +634,7 @@ class Ctx:
633
634
  if self.window.core.ctx.get_current() == id:
634
635
  items = self.window.core.ctx.all() # TODO: get by meta id(s)
635
636
  self.window.core.history.remove_items(items)
637
+ updated_current = True
636
638
  self.window.core.attachments.context.delete_by_meta_id(id)
637
639
  self.window.core.ctx.remove(id)
638
640
  self.remove_selected(id)
@@ -645,7 +647,8 @@ class Ctx:
645
647
 
646
648
  if updated:
647
649
  self.update_and_restore()
648
- self.window.controller.ui.tabs.update_title_current("...")
650
+ if updated_current:
651
+ self.window.controller.ui.tabs.update_title_current("...")
649
652
 
650
653
  def delete_meta_from_idx(self, id: int):
651
654
  """
@@ -47,7 +47,12 @@ class Common:
47
47
  :param width: Canvas width
48
48
  :param height: Canvas height
49
49
  """
50
- self.window.ui.painter.setFixedSize(QSize(width, height))
50
+ painter = self.window.ui.painter
51
+ if hasattr(painter, "set_canvas_size_pixels"):
52
+ painter.set_canvas_size_pixels(width, height)
53
+ else:
54
+ # required on image open
55
+ self.window.ui.painter.setFixedSize(QSize(width, height))
51
56
 
52
57
  def set_brush_mode(self, enabled: bool):
53
58
  """
@@ -81,14 +86,21 @@ class Common:
81
86
  if self._changing_canvas_size:
82
87
  return
83
88
 
84
- combo: QComboBox = self.window.ui.nodes['painter.select.canvas.size']
89
+ # Be resilient if combobox node is not present in a given UI layout
90
+ combo: Optional[QComboBox] = None
91
+ try:
92
+ if hasattr(self.window.ui, "nodes"):
93
+ combo = self.window.ui.nodes.get('painter.select.canvas.size', None)
94
+ except Exception:
95
+ combo = None
96
+
85
97
  painter = self.window.ui.painter
86
98
 
87
99
  # Heuristic to detect manual UI change vs programmatic call
88
100
  # - manual if: no arg, or int index (Qt int overload), or arg equals currentText/currentData
89
101
  raw_arg = selected
90
- current_text = combo.currentText()
91
- current_data = combo.currentData()
102
+ current_text = combo.currentText() if combo is not None else ""
103
+ current_data = combo.currentData() if combo is not None else None
92
104
  current_data_str = current_data if isinstance(current_data, str) else None
93
105
  is_manual = (
94
106
  raw_arg is None
@@ -105,8 +117,15 @@ class Common:
105
117
  if not selected_norm:
106
118
  return
107
119
 
120
+ # Use true logical canvas size when available
121
+ if hasattr(painter, "get_canvas_size"):
122
+ cur_sz = painter.get_canvas_size()
123
+ cur_val = f"{cur_sz.width()}x{cur_sz.height()}"
124
+ else:
125
+ cur_val = f"{painter.width()}x{painter.height()}"
126
+
108
127
  # Save undo only for manual changes and only if size will change
109
- will_change = selected_norm != f"{painter.width()}x{painter.height()}"
128
+ will_change = selected_norm != cur_val
110
129
  if is_manual and will_change:
111
130
  painter.saveForUndo()
112
131
 
@@ -124,9 +143,10 @@ class Common:
124
143
  self._sticky_custom_value = selected_norm
125
144
 
126
145
  # Ensure combo reflects single custom at index 0 (sticky respected), then select current value
127
- self._sync_canvas_size_combo(combo, selected_norm, sticky_to_keep=self._sticky_custom_value)
146
+ if combo is not None:
147
+ self._sync_canvas_size_combo(combo, selected_norm, sticky_to_keep=self._sticky_custom_value)
128
148
 
129
- # Apply canvas size; PainterWidget handles rescaling in resizeEvent
149
+ # Apply canvas size; PainterWidget handles rescaling in its own logic
130
150
  w, h = self.convert_to_size(selected_norm)
131
151
  self.set_canvas_size(w, h)
132
152
 
@@ -272,10 +292,22 @@ class Common:
272
292
  if self._changing_canvas_size:
273
293
  return
274
294
 
275
- combo: QComboBox = self.window.ui.nodes['painter.select.canvas.size']
295
+ combo: Optional[QComboBox] = None
296
+ try:
297
+ if hasattr(self.window.ui, "nodes"):
298
+ combo = self.window.ui.nodes.get('painter.select.canvas.size', None)
299
+ except Exception:
300
+ combo = None
301
+
276
302
  painter = self.window.ui.painter
277
303
 
278
- canvas_value = f"{painter.width()}x{painter.height()}"
304
+ # Use true logical canvas size, not widget size
305
+ if hasattr(painter, "get_canvas_size"):
306
+ sz = painter.get_canvas_size()
307
+ canvas_value = f"{sz.width()}x{sz.height()}"
308
+ else:
309
+ canvas_value = f"{painter.width()}x{painter.height()}"
310
+
279
311
  canvas_norm = self._normalize_canvas_value(canvas_value)
280
312
  if not canvas_norm:
281
313
  return
@@ -292,7 +324,8 @@ class Common:
292
324
  try:
293
325
  self._changing_canvas_size = True
294
326
  self._sticky_custom_value = sticky
295
- self._sync_canvas_size_combo(combo, canvas_norm, sticky_to_keep=sticky)
327
+ if combo is not None:
328
+ self._sync_canvas_size_combo(combo, canvas_norm, sticky_to_keep=sticky)
296
329
 
297
330
  # Persist canvas size only (do not change sticky config-scope)
298
331
  self.window.core.config.set('painter.canvas.size', canvas_norm)
@@ -409,7 +442,6 @@ class Common:
409
442
  combo.setCurrentText(value)
410
443
  else:
411
444
  # Current value is custom: ensure it exists at index 0 and select it
412
- # If sticky differs or is None, overwrite/create the custom at index 0 to reflect true current value.
413
445
  if not sticky_to_keep or sticky_to_keep != value:
414
446
  self._ensure_custom_index0(combo, value, predef)
415
447
  if combo.currentIndex() != 0:
@@ -480,3 +480,73 @@ class Filesystem:
480
480
  else:
481
481
  files = [os.path.join(path, f) for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
482
482
  return files
483
+
484
+ # ===== Helpers for pack/unpack =====
485
+
486
+ def common_parent_dir(self, paths: List[str]) -> str:
487
+ """
488
+ Return a sensible common parent directory for the given paths.
489
+ For a single directory selection returns that directory; for a single file returns its parent.
490
+ For multiple selections returns a common existing parent, if resolvable, otherwise the parent of the first path.
491
+ """
492
+ if not paths:
493
+ return self.window.core.config.get_user_path()
494
+ norm = []
495
+ for p in paths:
496
+ p = os.path.abspath(p)
497
+ norm.append(p if os.path.isdir(p) else os.path.dirname(p))
498
+ if len(norm) == 1:
499
+ return norm[0]
500
+ try:
501
+ cp = os.path.commonpath(norm)
502
+ if os.path.isdir(cp):
503
+ return cp
504
+ return os.path.dirname(cp)
505
+ except Exception:
506
+ return norm[0]
507
+
508
+ def unique_path(self, directory: str, base_name: str, ext: str) -> str:
509
+ """
510
+ Return a unique file path within 'directory' for 'base_name' and 'ext' (ext should include dot or be empty).
511
+ Uses 'name', 'name (1)', 'name (2)', ... scheme.
512
+ """
513
+ os.makedirs(directory, exist_ok=True)
514
+ candidate = os.path.join(directory, f"{base_name}{ext}")
515
+ if not os.path.exists(candidate):
516
+ return candidate
517
+ i = 1
518
+ while True:
519
+ cand = os.path.join(directory, f"{base_name} ({i}){ext}")
520
+ if not os.path.exists(cand):
521
+ return cand
522
+ i += 1
523
+
524
+ def unique_dir(self, directory: str, base_name: str) -> str:
525
+ """
526
+ Return a unique directory path 'directory/base_name', adding ' (n)' suffix when needed.
527
+ """
528
+ os.makedirs(directory, exist_ok=True)
529
+ candidate = os.path.join(directory, base_name)
530
+ if not os.path.exists(candidate):
531
+ return candidate
532
+ i = 1
533
+ while True:
534
+ cand = os.path.join(directory, f"{base_name} ({i})")
535
+ if not os.path.exists(cand):
536
+ return cand
537
+ i += 1
538
+
539
+ def strip_archive_name(self, filename: str) -> str:
540
+ """
541
+ Strip known archive extensions (.zip, .tar, .tar.gz, .tar.bz2, .tar.xz, .tgz, .tbz2, .txz) from a filename.
542
+ Returns filename without extension(s).
543
+ """
544
+ combos = ['.tar.gz', '.tar.bz2', '.tar.xz', '.tgz', '.tbz2', '.txz']
545
+ lower = filename.lower()
546
+ for suf in combos:
547
+ if lower.endswith(suf):
548
+ return filename[:-len(suf)]
549
+ root, ext = os.path.splitext(filename)
550
+ if ext.lower() in ('.zip', '.tar'):
551
+ return root
552
+ return root
@@ -84,4 +84,164 @@ class Packer:
84
84
  :param path: path to directory
85
85
  """
86
86
  if os.path.exists(path) and os.path.isdir(path):
87
- shutil.rmtree(path)
87
+ shutil.rmtree(path)
88
+
89
+ # ===== New high-level pack/unpack API (non-breaking) =====
90
+
91
+ def can_unpack(self, path: str) -> bool:
92
+ """
93
+ Check using stdlib detectors whether given file is a supported archive.
94
+ """
95
+ if not (path and os.path.isfile(path)):
96
+ return False
97
+ try:
98
+ import zipfile, tarfile
99
+ return zipfile.is_zipfile(path) or tarfile.is_tarfile(path)
100
+ except Exception:
101
+ return False
102
+
103
+ def _detect_kind(self, path: str) -> str:
104
+ """
105
+ Detect archive kind: 'zip' or 'tar'. Returns '' if unknown.
106
+ """
107
+ try:
108
+ import zipfile, tarfile
109
+ if zipfile.is_zipfile(path):
110
+ return 'zip'
111
+ if tarfile.is_tarfile(path):
112
+ return 'tar'
113
+ except Exception:
114
+ pass
115
+ return ''
116
+
117
+ def pack_paths(self, paths: list, fmt: str, dest_dir: str = None, base_name: str = None) -> str:
118
+ """
119
+ Pack given paths into a single archive.
120
+
121
+ :param paths: list of files/dirs to include
122
+ :param fmt: 'zip' or 'tar.gz'
123
+ :param dest_dir: output directory (default: common parent of paths)
124
+ :param base_name: output archive base name without extension (optional)
125
+ :return: created archive path or empty string on error
126
+ """
127
+ if not paths:
128
+ return ""
129
+ fs = self.window.core.filesystem
130
+ paths = [os.path.abspath(p) for p in paths if p]
131
+ dest_dir = dest_dir or fs.common_parent_dir(paths)
132
+
133
+ if base_name is None:
134
+ if len(paths) == 1:
135
+ name = os.path.basename(paths[0].rstrip(os.sep))
136
+ if os.path.isfile(paths[0]):
137
+ root, _ = os.path.splitext(name)
138
+ base_name = root or name
139
+ else:
140
+ base_name = name
141
+ else:
142
+ base_name = "archive"
143
+
144
+ fmt = (fmt or "").lower()
145
+ if fmt == 'zip':
146
+ ext = ".zip"
147
+ out_path = fs.unique_path(dest_dir, base_name, ext)
148
+ try:
149
+ self._pack_zip(paths, out_path)
150
+ return out_path
151
+ except Exception as e:
152
+ try:
153
+ self.window.core.debug.log(e)
154
+ except Exception:
155
+ pass
156
+ return ""
157
+ elif fmt in ('tar.gz', 'tgz'):
158
+ ext = ".tar.gz"
159
+ out_path = fs.unique_path(dest_dir, base_name, ext)
160
+ try:
161
+ self._pack_tar_gz(paths, out_path)
162
+ return out_path
163
+ except Exception as e:
164
+ try:
165
+ self.window.core.debug.log(e)
166
+ except Exception:
167
+ pass
168
+ return ""
169
+ else:
170
+ return ""
171
+
172
+ def _pack_zip(self, paths: list, out_path: str):
173
+ """
174
+ Create ZIP archive with selected paths, preserving top-level names.
175
+ """
176
+ import zipfile
177
+ with zipfile.ZipFile(out_path, 'w', compression=zipfile.ZIP_DEFLATED) as zf:
178
+ for src in paths:
179
+ top = os.path.basename(src.rstrip(os.sep))
180
+ if os.path.isdir(src):
181
+ for root, dirs, files in os.walk(src):
182
+ rel = os.path.relpath(root, src)
183
+ arc_root = top if rel == "." else os.path.join(top, rel)
184
+ # Add empty directories explicitly
185
+ if not files and not dirs:
186
+ zinfo = zipfile.ZipInfo(arc_root + "/")
187
+ zf.writestr(zinfo, "")
188
+ for f in files:
189
+ absf = os.path.join(root, f)
190
+ arcf = os.path.join(arc_root, f)
191
+ zf.write(absf, arcf)
192
+ else:
193
+ zf.write(src, top)
194
+
195
+ def _pack_tar_gz(self, paths: list, out_path: str):
196
+ """
197
+ Create TAR.GZ archive with selected paths, preserving top-level names.
198
+ """
199
+ import tarfile
200
+ with tarfile.open(out_path, 'w:gz') as tf:
201
+ for src in paths:
202
+ top = os.path.basename(src.rstrip(os.sep))
203
+ tf.add(src, arcname=top, recursive=True)
204
+
205
+ def unpack_to_dir(self, path: str, dest_dir: str) -> str:
206
+ """
207
+ Unpack archive at 'path' into 'dest_dir'.
208
+
209
+ :param path: archive file path
210
+ :param dest_dir: destination directory to extract into
211
+ :return: dest_dir on success, empty string otherwise
212
+ """
213
+ if not self.can_unpack(path):
214
+ return ""
215
+ try:
216
+ import zipfile, tarfile
217
+ os.makedirs(dest_dir, exist_ok=True)
218
+ kind = self._detect_kind(path)
219
+ if kind == 'zip':
220
+ with zipfile.ZipFile(path, 'r') as zf:
221
+ zf.extractall(dest_dir)
222
+ elif kind == 'tar':
223
+ with tarfile.open(path, 'r:*') as tf:
224
+ tf.extractall(dest_dir)
225
+ else:
226
+ return ""
227
+ return dest_dir
228
+ except Exception as e:
229
+ try:
230
+ self.window.core.debug.log(e)
231
+ except Exception:
232
+ pass
233
+ return ""
234
+
235
+ def unpack_to_sibling_dir(self, path: str) -> str:
236
+ """
237
+ Unpack archive into directory placed next to the archive, named after archive base name.
238
+
239
+ :param path: archive file path
240
+ :return: created directory path or empty string
241
+ """
242
+ if not (path and os.path.isfile(path)):
243
+ return ""
244
+ parent = os.path.dirname(path)
245
+ base = self.window.core.filesystem.strip_archive_name(os.path.basename(path))
246
+ out_dir = self.window.core.filesystem.unique_dir(parent, base)
247
+ return self.unpack_to_dir(path, out_dir)
@@ -152,7 +152,7 @@ class Image(QObject):
152
152
  """
153
153
  return {
154
154
  "type": "combo",
155
- "slider": True,
155
+ #"search": False,
156
156
  "label": "img_resolution",
157
157
  "value": "1024x1024",
158
158
  "keys": self.get_available_resolutions(),
@@ -166,7 +166,7 @@ class Image(QObject):
166
166
  """
167
167
  return {
168
168
  "type": "combo",
169
- "slider": True,
169
+ #"search": False,
170
170
  "label": "img_mode",
171
171
  "value": "image",
172
172
  "keys": self.get_available_modes(),
@@ -276,7 +276,7 @@ class Video(QObject):
276
276
  """
277
277
  return {
278
278
  "type": "combo",
279
- "slider": True,
279
+ # "search": False,
280
280
  "label": "video.aspect_ratio",
281
281
  "value": "16:9",
282
282
  "keys": self.get_available_aspect_ratio(),
@@ -290,7 +290,7 @@ class Video(QObject):
290
290
  """
291
291
  return {
292
292
  "type": "combo",
293
- "slider": True,
293
+ # "search": False,
294
294
  "label": "video.resolution",
295
295
  "value": "720p",
296
296
  "keys": self.get_available_resolutions(),
@@ -304,7 +304,6 @@ class Video(QObject):
304
304
  """
305
305
  return {
306
306
  "type": "int",
307
- "slider": False,
308
307
  "label": "video.duration",
309
308
  "value": 8,
310
309
  "placeholder": "s",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.0",
4
- "app.version": "2.7.0",
3
+ "version": "2.7.1",
4
+ "app.version": "2.7.1",
5
5
  "updated_at": "2025-12-28T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.0",
4
- "app.version": "2.7.0",
3
+ "version": "2.7.1",
4
+ "app.version": "2.7.1",
5
5
  "updated_at": "2025-12-28T00:00:00"
6
6
  },
7
7
  "items": {
@@ -179,13 +179,12 @@ NodeEditor {{
179
179
  /* ComboBox */
180
180
  QComboBox QAbstractItemView {{
181
181
  border: 1px solid rgba(0,0,0,0.18);
182
- border-radius: 0;
183
- outline: 0;
184
182
  }}
185
183
 
186
184
  QListView#ComboPopupList {{
187
- border-radius: 0;
188
- outline: 0;
185
+ border-radius: 10px;
186
+ background: #1f2123;
187
+ border: 2px solid #4f5b62;
189
188
  }}
190
189
 
191
190
  QComboBox QAbstractItemView::item,
@@ -212,4 +211,12 @@ QListView#ComboPopupList::item:disabled {{
212
211
 
213
212
  QComboBox QAbstractItemView::item:hover,
214
213
  QListView#ComboPopupList::item:hover {{ }}
215
- QListView#ComboPopupList > QWidget#ComboPopupViewport {{ }}
214
+
215
+ QWidget#ComboPopupWindow {{
216
+ background: transparent;
217
+ border: 0;
218
+ }}
219
+ QListView#ComboPopupList > QWidget#ComboPopupViewport {{
220
+ background: transparent;
221
+ border-radius: 0px;
222
+ }}
@@ -294,14 +294,15 @@ NodeEditor {{
294
294
 
295
295
  /* ComboBox */
296
296
  QComboBox QAbstractItemView {{
297
- border: 1px solid rgba(0,0,0,0.18);
298
- border-radius: 0;
297
+ border: 0px;
298
+ border-radius: 10px;
299
299
  outline: 0;
300
300
  }}
301
301
 
302
302
  QListView#ComboPopupList {{
303
- border-radius: 0;
303
+ border-radius: 10px;
304
304
  outline: 0;
305
+ border: 0px solid #d6d6d6;
305
306
  }}
306
307
 
307
308
  QComboBox QAbstractItemView::item,
@@ -328,4 +329,11 @@ QListView#ComboPopupList::item:disabled {{
328
329
 
329
330
  QComboBox QAbstractItemView::item:hover,
330
331
  QListView#ComboPopupList::item:hover {{ }}
331
- QListView#ComboPopupList > QWidget#ComboPopupViewport {{ }}
332
+ QWidget#ComboPopupWindow {{
333
+ background: red;
334
+ border: 0;
335
+ }}
336
+ QListView#ComboPopupList > QWidget#ComboPopupViewport {{
337
+ background: red;
338
+ border-radius: 10px;
339
+ }}
@@ -38,6 +38,7 @@ action.open_dir_src = Quellverzeichnis öffnen
38
38
  action.open_dir_storage = Speicherverzeichnis öffnen
39
39
  action.open_new_tab = In neuem Tab öffnen
40
40
  action.open_new_window = Öffnen (neues Fenster)
41
+ action.pack = Einpacken
41
42
  action.paste = Einfügen
42
43
  action.pin = Oben anheften
43
44
  action.preview = Vorschau
@@ -66,6 +67,7 @@ action.tab.move.right = In die rechte Spalte verschieben
66
67
  action.touch = Datei erstellen...
67
68
  action.truncate = Alles löschen
68
69
  action.undo = Rückgängig
70
+ action.unpack = Auspacken
69
71
  action.unpin = Loslösen
70
72
  action.upload = Dateien hier hochladen...
71
73
  action.use = Verwenden
@@ -38,6 +38,7 @@ action.open_dir_src = Open Source Directory
38
38
  action.open_dir_storage = Open Storage directory
39
39
  action.open_new_tab = Open in a new tab
40
40
  action.open_new_window = Open (new window)
41
+ action.pack = Pack
41
42
  action.paste = Paste
42
43
  action.pin = Pin on top
43
44
  action.preview = Preview
@@ -66,6 +67,7 @@ action.tab.move.right = Move to right column
66
67
  action.touch = Create file...
67
68
  action.truncate = Truncate
68
69
  action.undo = Undo
70
+ action.unpack = Unpack
69
71
  action.unpin = Unpin
70
72
  action.upload = Upload files here...
71
73
  action.use = Use
@@ -38,6 +38,7 @@ action.open_dir_src = Abrir directorio fuente
38
38
  action.open_dir_storage = Abrir directorio de almacenamiento
39
39
  action.open_new_tab = Abrir en una nueva pestaña
40
40
  action.open_new_window = Abrir (nueva ventana)
41
+ action.pack = Empaquetar
41
42
  action.paste = Pegar
42
43
  action.pin = Fijar en la parte superior
43
44
  action.preview = Vista previa
@@ -66,6 +67,7 @@ action.tab.move.right = Mover a la columna derecha
66
67
  action.touch = Crear archivo...
67
68
  action.truncate = Borrar todo
68
69
  action.undo = Deshacer
70
+ action.unpack = Desempaquetar
69
71
  action.unpin = Desanclar
70
72
  action.upload = Sube archivos aquí...
71
73
  action.use = Usar
@@ -38,6 +38,7 @@ action.open_dir_src = Ouvrir le répertoire source
38
38
  action.open_dir_storage = Ouvrir le répertoire de stockage
39
39
  action.open_new_tab = Ouvrir dans un nouvel onglet
40
40
  action.open_new_window = Ouvrir (nouvelle fenêtre)
41
+ action.pack = Emballer
41
42
  action.paste = Coller
42
43
  action.pin = Épingler en haut
43
44
  action.preview = Aperçu
@@ -66,6 +67,7 @@ action.tab.move.right = Déplacer vers la colonne de droite
66
67
  action.touch = Créer un fichier...
67
68
  action.truncate = Tout effacer
68
69
  action.undo = Annuler
70
+ action.unpack = Déballer
69
71
  action.unpin = Détacher
70
72
  action.upload = Téléchargez des fichiers ici...
71
73
  action.use = Utiliser
@@ -38,6 +38,7 @@ action.open_dir_src = Apri la cartella sorgente
38
38
  action.open_dir_storage = Apri la cartella di archiviazione
39
39
  action.open_new_tab = Apri in una nuova scheda
40
40
  action.open_new_window = Apri (nuova finestra)
41
+ action.pack = Imballare
41
42
  action.paste = Incolla
42
43
  action.pin = Fissa in alto
43
44
  action.preview = Anteprima
@@ -66,6 +67,7 @@ action.tab.move.right = Sposta nella colonna di destra
66
67
  action.touch = Crea file...
67
68
  action.truncate = Cancellare tutto
68
69
  action.undo = Annulla
70
+ action.unpack = Scartare
69
71
  action.unpin = Sgancia
70
72
  action.upload = Carica file qui...
71
73
  action.use = Usa
@@ -27,7 +27,7 @@ action.group.new = Nowa grupa
27
27
  action.group.remove = Usuń z grupy
28
28
  action.idx = Indeksuj w LlamaIndex...
29
29
  action.idx.remove = Usuń z
30
- action.import = Importuj
30
+ action.import = Importuj
31
31
  action.mkdir = Utwórz katalog...
32
32
  action.move_to = Przenieś do
33
33
  action.new = Nowy...
@@ -38,6 +38,7 @@ action.open_dir_src = Otwórz katalog źródłowy
38
38
  action.open_dir_storage = Otwórz katalog magazynowy
39
39
  action.open_new_tab = Otwórz w nowej karcie
40
40
  action.open_new_window = Otwórz (w nowym oknie)
41
+ action.pack = Spakuj
41
42
  action.paste = Wklej
42
43
  action.pin = Przypnij na górze
43
44
  action.preview = Podgląd
@@ -66,6 +67,7 @@ action.tab.move.right = Przenieś do prawej kolumny
66
67
  action.touch = Utwórz plik...
67
68
  action.truncate = Wyczyść wszystko
68
69
  action.undo = Cofnij
70
+ action.unpack = Rozpakuj
69
71
  action.unpin = Odepnij
70
72
  action.upload = Prześlij tutaj pliki...
71
73
  action.use = Użyj
@@ -38,6 +38,7 @@ action.open_dir_src = Відкрити вихідний каталог
38
38
  action.open_dir_storage = Відкрити каталог зберігання
39
39
  action.open_new_tab = Відкрити у новій вкладці
40
40
  action.open_new_window = Відкрити (нове вікно)
41
+ action.pack = Запакувати
41
42
  action.paste = Вставити
42
43
  action.pin = Прикріпити зверху
43
44
  action.preview = Попередній перегляд
@@ -66,6 +67,7 @@ action.tab.move.right = Перемістити в праву колонку
66
67
  action.touch = Створити файл...
67
68
  action.truncate = Очистити все
68
69
  action.undo = Скасувати
70
+ action.unpack = Розпакувати
69
71
  action.unpin = Відкріпити
70
72
  action.upload = Завантажте файли тут...
71
73
  action.use = Використовуйте
@@ -38,6 +38,7 @@ action.open_dir_src = 打开源目录
38
38
  action.open_dir_storage = 打开存储目录
39
39
  action.open_new_tab = 在新标签页中打开
40
40
  action.open_new_window = 打开(新窗口)
41
+ action.pack = 打包
41
42
  action.paste = 粘贴
42
43
  action.pin = 置頂
43
44
  action.preview = 预览
@@ -66,6 +67,7 @@ action.tab.move.right = 移到右列
66
67
  action.touch = 創建文件...
67
68
  action.truncate = 截斷
68
69
  action.undo = 撤銷
70
+ action.unpack = 解压
69
71
  action.unpin = 取消置頂
70
72
  action.upload = 在這裡上傳文件...
71
73
  action.use = 使用