pygpt-net 2.4.42__py3-none-any.whl → 2.4.45__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.
- CHANGELOG.md +15 -0
- README.md +21 -2
- pygpt_net/CHANGELOG.txt +15 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/controller/attachment.py +31 -3
- pygpt_net/controller/chat/attachment.py +37 -36
- pygpt_net/controller/config/placeholder.py +6 -4
- pygpt_net/controller/idx/common.py +7 -3
- pygpt_net/controller/lang/mapping.py +32 -9
- pygpt_net/core/attachments/__init__.py +7 -2
- pygpt_net/core/attachments/context.py +52 -34
- pygpt_net/core/db/__init__.py +2 -1
- pygpt_net/core/debug/attachments.py +1 -0
- pygpt_net/core/idx/__init__.py +8 -3
- pygpt_net/core/idx/indexing.py +24 -7
- pygpt_net/core/idx/ui/__init__.py +22 -0
- pygpt_net/core/idx/ui/loaders.py +217 -0
- pygpt_net/data/config/config.json +4 -4
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/config/modes.json +3 -3
- pygpt_net/data/config/settings.json +5 -5
- pygpt_net/data/css/style.css +1 -0
- pygpt_net/data/locale/locale.de.ini +4 -4
- pygpt_net/data/locale/locale.en.ini +11 -9
- pygpt_net/data/locale/locale.es.ini +4 -4
- pygpt_net/data/locale/locale.fr.ini +4 -4
- pygpt_net/data/locale/locale.it.ini +4 -4
- pygpt_net/data/locale/locale.pl.ini +4 -4
- pygpt_net/data/locale/locale.uk.ini +4 -4
- pygpt_net/data/locale/locale.zh.ini +4 -4
- pygpt_net/data/locale/plugin.mailer.en.ini +5 -5
- pygpt_net/item/attachment.py +5 -1
- pygpt_net/item/ctx.py +99 -2
- pygpt_net/migrations/Version20241215110000.py +25 -0
- pygpt_net/migrations/__init__.py +3 -1
- pygpt_net/plugin/cmd_files/__init__.py +3 -2
- pygpt_net/provider/core/attachment/json_file.py +4 -1
- pygpt_net/provider/core/config/patch.py +12 -0
- pygpt_net/provider/core/ctx/db_sqlite/storage.py +50 -7
- pygpt_net/provider/core/ctx/db_sqlite/utils.py +29 -5
- pygpt_net/provider/loaders/base.py +14 -0
- pygpt_net/provider/loaders/hub/google/gmail.py +2 -2
- pygpt_net/provider/loaders/hub/yt/base.py +5 -0
- pygpt_net/provider/loaders/web_database.py +13 -5
- pygpt_net/provider/loaders/web_github_issues.py +18 -1
- pygpt_net/provider/loaders/web_github_repo.py +10 -0
- pygpt_net/provider/loaders/web_google_calendar.py +9 -1
- pygpt_net/provider/loaders/web_google_docs.py +6 -1
- pygpt_net/provider/loaders/web_google_drive.py +10 -1
- pygpt_net/provider/loaders/web_google_gmail.py +5 -3
- pygpt_net/provider/loaders/web_google_keep.py +5 -1
- pygpt_net/provider/loaders/web_google_sheets.py +5 -1
- pygpt_net/provider/loaders/web_microsoft_onedrive.py +15 -1
- pygpt_net/provider/loaders/web_page.py +4 -2
- pygpt_net/provider/loaders/web_rss.py +3 -1
- pygpt_net/provider/loaders/web_sitemap.py +9 -3
- pygpt_net/provider/loaders/web_twitter.py +4 -2
- pygpt_net/provider/loaders/web_yt.py +17 -2
- pygpt_net/provider/vector_stores/ctx_attachment.py +1 -1
- pygpt_net/tools/indexer/__init__.py +8 -40
- pygpt_net/tools/indexer/ui/web.py +33 -80
- pygpt_net/ui/layout/ctx/ctx_list.py +86 -18
- pygpt_net/ui/widget/dialog/url.py +162 -14
- pygpt_net/ui/widget/element/group.py +15 -2
- pygpt_net/ui/widget/lists/context.py +23 -9
- pygpt_net/utils.py +1 -1
- {pygpt_net-2.4.42.dist-info → pygpt_net-2.4.45.dist-info}/METADATA +22 -3
- {pygpt_net-2.4.42.dist-info → pygpt_net-2.4.45.dist-info}/RECORD +71 -68
- {pygpt_net-2.4.42.dist-info → pygpt_net-2.4.45.dist-info}/LICENSE +0 -0
- {pygpt_net-2.4.42.dist-info → pygpt_net-2.4.45.dist-info}/WHEEL +0 -0
- {pygpt_net-2.4.42.dist-info → pygpt_net-2.4.45.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import json
|
@@ -30,18 +30,26 @@ class Loader(BaseLoader):
|
|
30
30
|
"args": {
|
31
31
|
"folder_id": {
|
32
32
|
"type": "str",
|
33
|
+
"label": "Folder ID",
|
33
34
|
},
|
34
35
|
"file_ids": {
|
35
36
|
"type": "list",
|
37
|
+
"label": "File IDs",
|
38
|
+
"description": "List of file ids, separated by comma (,)",
|
36
39
|
},
|
37
40
|
"mime_types": {
|
38
41
|
"type": "list",
|
42
|
+
"label": "Mime Types",
|
43
|
+
"description": "List of mime types, separated by comma (,)",
|
39
44
|
},
|
40
45
|
"folder_path": {
|
41
46
|
"type": "str",
|
47
|
+
"label": "Folder Path",
|
42
48
|
},
|
43
49
|
"file_paths": {
|
44
50
|
"type": "list",
|
51
|
+
"label": "File Paths",
|
52
|
+
"description": "List of file paths, separated by comma (,)",
|
45
53
|
},
|
46
54
|
},
|
47
55
|
}
|
@@ -98,10 +106,14 @@ class Loader(BaseLoader):
|
|
98
106
|
if "file_ids" in kwargs and kwargs.get("file_ids"):
|
99
107
|
if isinstance(kwargs.get("file_ids"), list):
|
100
108
|
args["file_ids"] = kwargs.get("file_ids") # list of file ids
|
109
|
+
elif isinstance(kwargs.get("file_ids"), str):
|
110
|
+
args["file_ids"] = self.explode(kwargs.get("file_ids"))
|
101
111
|
|
102
112
|
if "mime_types" in kwargs and kwargs.get("mime_types"):
|
103
113
|
if isinstance(kwargs.get("mime_types"), list):
|
104
114
|
args["mime_types"] = kwargs.get("mime_types") # list of mime types
|
115
|
+
elif isinstance(kwargs.get("mime_types"), str):
|
116
|
+
args["mime_types"] = self.explode(kwargs.get("mime_types"))
|
105
117
|
|
106
118
|
if "folder_path" in kwargs and kwargs.get("folder_path"):
|
107
119
|
if isinstance(kwargs.get("folder_path"), str):
|
@@ -110,4 +122,6 @@ class Loader(BaseLoader):
|
|
110
122
|
if "file_paths" in kwargs and kwargs.get("file_paths"):
|
111
123
|
if isinstance(kwargs.get("file_paths"), list):
|
112
124
|
args["file_paths"] = kwargs.get("file_paths") # list of file paths
|
125
|
+
elif isinstance(kwargs.get("file_paths"), str):
|
126
|
+
args["file_paths"] = self.explode(kwargs.get("file_paths"))
|
113
127
|
return args
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from llama_index.core.readers.base import BaseReader
|
@@ -19,7 +19,7 @@ class Loader(BaseLoader):
|
|
19
19
|
def __init__(self, *args, **kwargs):
|
20
20
|
super().__init__(*args, **kwargs)
|
21
21
|
self.id = "webpage"
|
22
|
-
self.name = "
|
22
|
+
self.name = "Webpage"
|
23
23
|
self.type = ["web"]
|
24
24
|
self.instructions = [
|
25
25
|
{
|
@@ -28,6 +28,8 @@ class Loader(BaseLoader):
|
|
28
28
|
"args": {
|
29
29
|
"url": {
|
30
30
|
"type": "str",
|
31
|
+
"label": "URL",
|
32
|
+
"description": "URL of the webpage to index, e.g. https://www.example.com",
|
31
33
|
},
|
32
34
|
},
|
33
35
|
}
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from llama_index.core.readers.base import BaseReader
|
@@ -28,6 +28,8 @@ class Loader(BaseLoader):
|
|
28
28
|
"args": {
|
29
29
|
"url": {
|
30
30
|
"type": "str",
|
31
|
+
"label": "URL",
|
32
|
+
"description": "URL to RSS feed, e.g. https://example.com/feed.xml",
|
31
33
|
},
|
32
34
|
},
|
33
35
|
}
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from llama_index.core.readers.base import BaseReader
|
@@ -23,11 +23,13 @@ class Loader(BaseLoader):
|
|
23
23
|
self.type = ["web"]
|
24
24
|
self.instructions = [
|
25
25
|
{
|
26
|
-
"
|
27
|
-
"description": "read
|
26
|
+
"sitemap": {
|
27
|
+
"description": "read all web pages from sitemap.xml",
|
28
28
|
"args": {
|
29
29
|
"url": {
|
30
30
|
"type": "str",
|
31
|
+
"label": "URL",
|
32
|
+
"description": "URL to sitemap XML, e.g. https://example.com/sitemap.xml, all pages will be read",
|
31
33
|
},
|
32
34
|
},
|
33
35
|
}
|
@@ -41,6 +43,10 @@ class Loader(BaseLoader):
|
|
41
43
|
"html_to_text": "bool",
|
42
44
|
"limit": "int",
|
43
45
|
}
|
46
|
+
self.init_args_desc = {
|
47
|
+
"html_to_text": "Whether to convert HTML to text",
|
48
|
+
"limit": "Maximum number of concurrent requests",
|
49
|
+
}
|
44
50
|
|
45
51
|
def get(self) -> BaseReader:
|
46
52
|
"""
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import json
|
@@ -30,9 +30,11 @@ class Loader(BaseLoader):
|
|
30
30
|
"args": {
|
31
31
|
"users": {
|
32
32
|
"type": "list",
|
33
|
+
"label": "Twitter/X usernames",
|
33
34
|
},
|
34
35
|
"max_tweets": {
|
35
36
|
"type": "int",
|
37
|
+
"label": "Max tweets",
|
36
38
|
},
|
37
39
|
},
|
38
40
|
}
|
@@ -80,7 +82,7 @@ class Loader(BaseLoader):
|
|
80
82
|
if isinstance(kwargs.get("users"), list):
|
81
83
|
args["twitterhandles"] = kwargs.get("users") # usernames
|
82
84
|
elif isinstance(kwargs.get("users"), str):
|
83
|
-
args["twitterhandles"] =
|
85
|
+
args["twitterhandles"] = self.explode(kwargs.get("users"))
|
84
86
|
|
85
87
|
if "max_tweets" in kwargs and kwargs.get("max_tweets"):
|
86
88
|
if isinstance(kwargs.get("max_tweets"), int):
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from llama_index.core.readers.base import BaseReader
|
@@ -28,11 +28,25 @@ class Loader(BaseLoader):
|
|
28
28
|
"args": {
|
29
29
|
"url": {
|
30
30
|
"type": "str",
|
31
|
+
"label": "Youtube URL",
|
32
|
+
"description": "URL of the YouTube video, e.g. https://www.youtube.com/watch?v=CRRlbK5w8AE",
|
31
33
|
},
|
32
34
|
},
|
33
35
|
}
|
34
36
|
}
|
35
37
|
]
|
38
|
+
self.init_args = {
|
39
|
+
"languages": ["en"],
|
40
|
+
}
|
41
|
+
self.init_args_types = {
|
42
|
+
"languages": "list",
|
43
|
+
}
|
44
|
+
self.init_args_labels = {
|
45
|
+
"languages": "Languages",
|
46
|
+
}
|
47
|
+
self.init_args_desc = {
|
48
|
+
"languages": "List of languages to extract from the video, separated by comma (,), e.g. 'en,de,fr'. Default is 'en'",
|
49
|
+
}
|
36
50
|
|
37
51
|
def get(self) -> BaseReader:
|
38
52
|
"""
|
@@ -40,7 +54,8 @@ class Loader(BaseLoader):
|
|
40
54
|
|
41
55
|
:return: Data reader instance
|
42
56
|
"""
|
43
|
-
|
57
|
+
args = self.get_args()
|
58
|
+
return YoutubeTranscriptReader(**args)
|
44
59
|
|
45
60
|
def prepare_args(self, **kwargs) -> dict:
|
46
61
|
"""
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.12.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import datetime
|
@@ -311,48 +311,16 @@ class IndexerTool(BaseTool):
|
|
311
311
|
|
312
312
|
:param force: force indexing
|
313
313
|
"""
|
314
|
-
input_params =
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
314
|
+
result, loader, input_params, input_config = self.window.core.idx.ui.loaders.handle_options(
|
315
|
+
self.window.ui.nodes["tool.indexer.web.loader"],
|
316
|
+
"tool.indexer.web.loader.option",
|
317
|
+
"tool.indexer.web.loader.config",
|
318
|
+
)
|
319
|
+
if not result:
|
319
320
|
self.window.ui.dialogs.alert(trans("tool.indexer.alert.no_loader"))
|
320
321
|
return
|
321
|
-
loaders = self.window.core.idx.indexing.get_external_instructions()
|
322
|
-
if loader in loaders:
|
323
|
-
params = loaders[loader]
|
324
|
-
for k in params["args"]:
|
325
|
-
key_path = "tool.indexer.web.loader.option." + loader + "." + k
|
326
|
-
if key_path in self.window.ui.nodes:
|
327
|
-
input_params[k] = self.window.ui.nodes[key_path].text()
|
328
322
|
|
329
|
-
|
330
|
-
if loader in loaders:
|
331
|
-
params = loaders[loader]
|
332
|
-
for k in params:
|
333
|
-
key_path = "tool.indexer.web.loader.config." + loader + "." + k
|
334
|
-
type = params[k]["type"]
|
335
|
-
if key_path in self.window.ui.nodes:
|
336
|
-
tmp_value = self.window.ui.nodes[key_path].text()
|
337
|
-
try:
|
338
|
-
if tmp_value:
|
339
|
-
if type == "int":
|
340
|
-
tmp_value = int(tmp_value)
|
341
|
-
elif type == "float":
|
342
|
-
tmp_value = float(tmp_value)
|
343
|
-
elif type == "bool":
|
344
|
-
if tmp_value.lower() in ["true", "1"]:
|
345
|
-
tmp_value = True
|
346
|
-
else:
|
347
|
-
tmp_value = False
|
348
|
-
elif type == "list":
|
349
|
-
tmp_value = tmp_value.split(",")
|
350
|
-
elif type == "dict":
|
351
|
-
tmp_value = json.loads(tmp_value)
|
352
|
-
input_config[k] = tmp_value
|
353
|
-
except Exception as e:
|
354
|
-
self.window.core.debug.log(e)
|
355
|
-
self.window.ui.dialogs.alert(e)
|
323
|
+
is_replace = self.window.ui.nodes["tool.indexer.web.options.replace"].isChecked()
|
356
324
|
if not force:
|
357
325
|
self.window.ui.dialogs.confirm(
|
358
326
|
type="idx.tool.index",
|
@@ -6,16 +6,18 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
import json
|
13
13
|
|
14
14
|
from PySide6.QtCore import Qt
|
15
|
+
from PySide6.QtGui import QIcon
|
15
16
|
from PySide6.QtWidgets import QLabel, QVBoxLayout, QWidget, QCheckBox, QHBoxLayout, QScrollArea, \
|
16
17
|
QSizePolicy
|
17
18
|
|
18
|
-
from pygpt_net.ui.widget.element.
|
19
|
+
from pygpt_net.ui.widget.element.group import QVLine, QHLine
|
20
|
+
from pygpt_net.ui.widget.element.labels import HelpLabel, UrlLabel, IconLabel
|
19
21
|
from pygpt_net.ui.widget.option.combo import OptionCombo
|
20
22
|
from pygpt_net.ui.widget.option.input import OptionInput
|
21
23
|
from pygpt_net.utils import trans
|
@@ -33,15 +35,17 @@ class WebTab:
|
|
33
35
|
self.params_widget = None
|
34
36
|
|
35
37
|
def setup(self):
|
36
|
-
"""
|
37
|
-
Setup tab widget
|
38
|
-
"""
|
38
|
+
"""Setup tab widget"""
|
39
39
|
# get loaders list
|
40
40
|
loaders = self.window.controller.config.placeholder.apply_by_id("llama_index_loaders_web")
|
41
41
|
loaders_list = []
|
42
42
|
for loader in loaders:
|
43
|
-
|
44
|
-
|
43
|
+
k = list(loader.keys())[0]
|
44
|
+
key = k.replace("web_", "")
|
45
|
+
value = loader[k]
|
46
|
+
loaders_list.append({
|
47
|
+
key: value,
|
48
|
+
})
|
45
49
|
|
46
50
|
self.window.ui.nodes["tool.indexer.web.loader"] = OptionCombo(
|
47
51
|
self.window,
|
@@ -55,14 +59,25 @@ class WebTab:
|
|
55
59
|
)
|
56
60
|
|
57
61
|
self.window.ui.nodes["tool.indexer.web.loader"].layout.setContentsMargins(0, 0, 0, 0)
|
58
|
-
self.window.ui.nodes["tool.indexer.web.loader.label"] =
|
62
|
+
self.window.ui.nodes["tool.indexer.web.loader.label"] = HelpLabel(trans("tool.indexer.tab.web.loader"))
|
59
63
|
self.window.ui.add_hook("update.tool.indexer.web.loader", self.hook_loader_change)
|
60
64
|
|
61
65
|
self.window.ui.nodes["tool.indexer.web.options.label"] = HelpLabel(trans("tool.indexer.tab.web.source"))
|
62
|
-
|
66
|
+
|
67
|
+
config_label = HelpLabel(trans("tool.indexer.tab.web.cfg"))
|
68
|
+
config_label.setWordWrap(False)
|
69
|
+
|
70
|
+
config_label_layout = QHBoxLayout()
|
71
|
+
config_label_layout.addWidget(IconLabel(QIcon(":/icons/settings_filled.svg")))
|
72
|
+
config_label_layout.addWidget(config_label)
|
73
|
+
config_label_layout.setAlignment(Qt.AlignLeft)
|
74
|
+
|
75
|
+
self.window.ui.nodes["tool.indexer.web.config.label"] = QWidget()
|
76
|
+
self.window.ui.nodes["tool.indexer.web.config.label"].setLayout(config_label_layout)
|
77
|
+
|
63
78
|
self.window.ui.nodes["tool.indexer.web.config.help"] = UrlLabel(
|
64
79
|
trans("tool.indexer.tab.web.help"),
|
65
|
-
"https://pygpt.readthedocs.io/en/latest/
|
80
|
+
"https://pygpt.readthedocs.io/en/latest/configuration.html#data-loaders")
|
66
81
|
|
67
82
|
# --------------------------------------------------
|
68
83
|
|
@@ -78,7 +93,7 @@ class WebTab:
|
|
78
93
|
|
79
94
|
# params
|
80
95
|
params_layout.addWidget(self.window.ui.nodes["tool.indexer.web.options.label"])
|
81
|
-
inputs, groups = self.setup_loader_options()
|
96
|
+
inputs, groups = self.window.core.idx.ui.loaders.setup_loader_options()
|
82
97
|
for loader in inputs:
|
83
98
|
for k in inputs[loader]:
|
84
99
|
self.window.ui.nodes["tool.indexer.web.loader.option." + loader + "." + k] = inputs[loader][k]
|
@@ -87,9 +102,12 @@ class WebTab:
|
|
87
102
|
params_layout.addWidget(self.window.ui.nodes["tool.indexer.web.loader.option_group"][loader])
|
88
103
|
self.window.ui.nodes["tool.indexer.web.loader.option_group"][loader].hide() # hide on start
|
89
104
|
|
105
|
+
# separator
|
106
|
+
params_layout.addWidget(QHLine())
|
107
|
+
|
90
108
|
# config
|
91
109
|
params_layout.addWidget(self.window.ui.nodes["tool.indexer.web.config.label"])
|
92
|
-
inputs, groups = self.setup_loader_config()
|
110
|
+
inputs, groups = self.window.core.idx.ui.loaders.setup_loader_config()
|
93
111
|
for loader in inputs:
|
94
112
|
for k in inputs[loader]:
|
95
113
|
self.window.ui.nodes["tool.indexer.web.loader.config." + loader + "." + k] = inputs[loader][k]
|
@@ -99,6 +117,7 @@ class WebTab:
|
|
99
117
|
self.window.ui.nodes["tool.indexer.web.loader.config_group"][loader].hide() # hide on start
|
100
118
|
params_layout.addWidget(self.window.ui.nodes["tool.indexer.web.config.help"], alignment=Qt.AlignCenter)
|
101
119
|
|
120
|
+
# stretch
|
102
121
|
params_layout.addStretch(1)
|
103
122
|
|
104
123
|
self.params_widget = QWidget()
|
@@ -117,9 +136,10 @@ class WebTab:
|
|
117
136
|
|
118
137
|
self.window.ui.nodes["tool.indexer.provider"] = HelpLabel(self.window.core.config.get("llama.idx.storage"))
|
119
138
|
|
120
|
-
loader_layout =
|
139
|
+
loader_layout = QVBoxLayout()
|
121
140
|
loader_layout.addWidget(self.window.ui.nodes["tool.indexer.web.loader.label"])
|
122
141
|
loader_layout.addWidget(self.window.ui.nodes["tool.indexer.web.loader"])
|
142
|
+
loader_layout.setContentsMargins(0, 10, 0, 0)
|
123
143
|
|
124
144
|
options_layout = QVBoxLayout()
|
125
145
|
options_layout.addWidget(self.window.ui.nodes["tool.indexer.web.options.replace"])
|
@@ -177,70 +197,3 @@ class WebTab:
|
|
177
197
|
|
178
198
|
self.params_widget.adjustSize()
|
179
199
|
self.params_scroll.update()
|
180
|
-
|
181
|
-
def setup_loader_options(self):
|
182
|
-
"""
|
183
|
-
Setup loader options
|
184
|
-
"""
|
185
|
-
inputs = {}
|
186
|
-
groups = {}
|
187
|
-
loaders = self.window.core.idx.indexing.get_external_instructions()
|
188
|
-
for loader in loaders:
|
189
|
-
params = loaders[loader]
|
190
|
-
inputs[loader] = {}
|
191
|
-
group = QVBoxLayout()
|
192
|
-
for k in params["args"]:
|
193
|
-
widget = OptionInput(self.window, "tool.indexer", f"web.loader.{loader}.option.{k}", {
|
194
|
-
"label": k,
|
195
|
-
"value": "",
|
196
|
-
})
|
197
|
-
widget.setPlaceholderText(params["args"][k]["type"])
|
198
|
-
inputs[loader][k] = widget
|
199
|
-
row = QHBoxLayout() # cols
|
200
|
-
row.addWidget(QLabel(k))
|
201
|
-
row.addWidget(widget)
|
202
|
-
group.addLayout(row)
|
203
|
-
group_widget = QWidget()
|
204
|
-
group_widget.setLayout(group)
|
205
|
-
groups[loader] = group_widget
|
206
|
-
|
207
|
-
return inputs, groups
|
208
|
-
|
209
|
-
def setup_loader_config(self):
|
210
|
-
"""
|
211
|
-
Setup loader config
|
212
|
-
"""
|
213
|
-
inputs = {}
|
214
|
-
groups = {}
|
215
|
-
loaders = self.window.core.idx.indexing.get_external_config()
|
216
|
-
for loader in loaders:
|
217
|
-
params = loaders[loader]
|
218
|
-
inputs[loader] = {}
|
219
|
-
group = QVBoxLayout()
|
220
|
-
for k in params:
|
221
|
-
widget = OptionInput(self.window, "tool.indexer", f"web.loader.{loader}.config.{k}", {
|
222
|
-
"label": k,
|
223
|
-
"value": params[k]["value"],
|
224
|
-
})
|
225
|
-
try:
|
226
|
-
if params[k]["value"] is not None:
|
227
|
-
if params[k]["type"] == "list" and isinstance(params[k]["value"], list):
|
228
|
-
widget.setText(", ".join(params[k]["value"]))
|
229
|
-
elif params[k]["type"] == "dict" and isinstance(params[k]["value"], dict):
|
230
|
-
widget.setText(json.dumps(params[k]["value"]))
|
231
|
-
else:
|
232
|
-
widget.setText(str(params[k]["value"]))
|
233
|
-
except Exception as e:
|
234
|
-
self.window.core.debug.log(e)
|
235
|
-
|
236
|
-
widget.setPlaceholderText(params[k]["type"])
|
237
|
-
inputs[loader][k] = widget
|
238
|
-
row = QHBoxLayout() # cols
|
239
|
-
row.addWidget(QLabel(k))
|
240
|
-
row.addWidget(widget)
|
241
|
-
group.addLayout(row)
|
242
|
-
group_widget = QWidget()
|
243
|
-
group_widget.setLayout(group)
|
244
|
-
groups[loader] = group_widget
|
245
|
-
|
246
|
-
return inputs, groups
|
@@ -6,7 +6,7 @@
|
|
6
6
|
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
7
7
|
# MIT License #
|
8
8
|
# Created By : Marcin Szczygliński #
|
9
|
-
# Updated Date: 2024.12.
|
9
|
+
# Updated Date: 2024.12.16 01:00:00 #
|
10
10
|
# ================================================== #
|
11
11
|
|
12
12
|
from PySide6 import QtCore
|
@@ -81,9 +81,11 @@ class CtxList:
|
|
81
81
|
self.window.ui.models[id].removeRows(0, self.window.ui.models[id].rowCount())
|
82
82
|
|
83
83
|
if self.window.core.config.get("ctx.records.folders.top"):
|
84
|
+
self.update_items_pinned(id, data)
|
84
85
|
self.update_groups(id, data)
|
85
86
|
self.update_items(id, data)
|
86
87
|
else:
|
88
|
+
self.update_items_pinned(id, data)
|
87
89
|
self.update_items(id, data)
|
88
90
|
self.update_groups(id, data)
|
89
91
|
|
@@ -96,13 +98,43 @@ class CtxList:
|
|
96
98
|
"""
|
97
99
|
i = 0
|
98
100
|
last_dt_str = None
|
101
|
+
separators = self.window.core.config.get("ctx.records.separators")
|
102
|
+
pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
|
99
103
|
for meta_id in data:
|
100
104
|
if data[meta_id].group_id is None or data[meta_id].group_id == 0:
|
105
|
+
if data[meta_id].important:
|
106
|
+
continue
|
101
107
|
item = self.build_item(meta_id, data[meta_id], is_group=False)
|
102
|
-
if
|
103
|
-
if not item.isPinned or
|
108
|
+
if separators:
|
109
|
+
if not item.isPinned or pinned_separators:
|
104
110
|
if i == 0 or last_dt_str != item.dt:
|
105
|
-
section = self.build_date_section(item.dt)
|
111
|
+
section = self.build_date_section(item.dt, group=False)
|
112
|
+
if section:
|
113
|
+
self.window.ui.models[id].appendRow(section)
|
114
|
+
last_dt_str = item.dt
|
115
|
+
self.window.ui.models[id].appendRow(item)
|
116
|
+
i += 1
|
117
|
+
|
118
|
+
def update_items_pinned(self, id, data):
|
119
|
+
"""
|
120
|
+
Update items pinned
|
121
|
+
|
122
|
+
:param id: ID of the list
|
123
|
+
:param data: Data to update
|
124
|
+
"""
|
125
|
+
i = 0
|
126
|
+
last_dt_str = None
|
127
|
+
separators = self.window.core.config.get("ctx.records.separators")
|
128
|
+
pinned_separators = self.window.core.config.get("ctx.records.pinned.separators")
|
129
|
+
for meta_id in data:
|
130
|
+
if data[meta_id].group_id is None or data[meta_id].group_id == 0:
|
131
|
+
if not data[meta_id].important:
|
132
|
+
continue
|
133
|
+
item = self.build_item(meta_id, data[meta_id], is_group=False)
|
134
|
+
if separators:
|
135
|
+
if pinned_separators:
|
136
|
+
if i == 0 or last_dt_str != item.dt:
|
137
|
+
section = self.build_date_section(item.dt, group=False)
|
106
138
|
if section:
|
107
139
|
self.window.ui.models[id].appendRow(section)
|
108
140
|
last_dt_str = item.dt
|
@@ -116,21 +148,37 @@ class CtxList:
|
|
116
148
|
:param id: ID of the list
|
117
149
|
:param data: Data to update
|
118
150
|
"""
|
119
|
-
# get groups
|
120
|
-
groups = self.window.core.ctx.get_groups()
|
121
|
-
|
151
|
+
groups = self.window.core.ctx.get_groups() # get groups
|
122
152
|
for group_id in groups:
|
123
153
|
last_dt_str = None
|
124
154
|
group = groups[group_id]
|
125
155
|
c = self.count_in_group(group.id, data)
|
126
|
-
if c == 0 and self.window.core.ctx.get_search_string() is not None
|
156
|
+
if (c == 0 and self.window.core.ctx.get_search_string() is not None
|
157
|
+
and self.window.core.ctx.get_search_string() != ""):
|
127
158
|
continue # skip empty groups when searching
|
128
159
|
|
129
160
|
suffix = ""
|
130
161
|
if c > 0:
|
131
162
|
suffix = " (" + str(c) + ")"
|
163
|
+
is_attachment = group.has_additional_ctx()
|
132
164
|
group_name = group.name + suffix
|
133
165
|
group_item = GroupItem(QIcon(":/icons/folder_filled.svg"), group_name, group.id)
|
166
|
+
group_item.hasAttachments = group.has_additional_ctx()
|
167
|
+
custom_data = {
|
168
|
+
"is_group": True,
|
169
|
+
"is_attachment": is_attachment,
|
170
|
+
}
|
171
|
+
if is_attachment:
|
172
|
+
files = group.get_attachment_names()
|
173
|
+
num = len(files)
|
174
|
+
files_str = ", ".join(files)
|
175
|
+
if len(files_str) > 40:
|
176
|
+
files_str = files_str[:40] + '...'
|
177
|
+
tooltip_str = trans("attachments.ctx.tooltip.list").format(num=num) + ": " + files_str
|
178
|
+
group_item.setToolTip(tooltip_str)
|
179
|
+
|
180
|
+
group_item.setData(custom_data, QtCore.Qt.ItemDataRole.UserRole)
|
181
|
+
|
134
182
|
i = 0
|
135
183
|
for meta_id in data:
|
136
184
|
if data[meta_id].group_id != group.id:
|
@@ -139,7 +187,7 @@ class CtxList:
|
|
139
187
|
if self.window.core.config.get("ctx.records.groups.separators"):
|
140
188
|
if not item.isPinned or self.window.core.config.get("ctx.records.pinned.separators"):
|
141
189
|
if i == 0 or last_dt_str != item.dt:
|
142
|
-
section = self.build_date_section(item.dt)
|
190
|
+
section = self.build_date_section(item.dt, group=True)
|
143
191
|
if section:
|
144
192
|
group_item.appendRow(section)
|
145
193
|
last_dt_str = item.dt
|
@@ -178,6 +226,17 @@ class CtxList:
|
|
178
226
|
:return: Item
|
179
227
|
"""
|
180
228
|
append_dt = True
|
229
|
+
is_important = False
|
230
|
+
is_attachment = False
|
231
|
+
in_group = False
|
232
|
+
label = data.label
|
233
|
+
if data.important:
|
234
|
+
is_important = True
|
235
|
+
if data.has_additional_ctx():
|
236
|
+
is_attachment = True
|
237
|
+
if data.group:
|
238
|
+
in_group = True
|
239
|
+
|
181
240
|
if is_group:
|
182
241
|
if self.window.core.config.get("ctx.records.groups.separators"):
|
183
242
|
append_dt = False
|
@@ -206,35 +265,44 @@ class CtxList:
|
|
206
265
|
mode_str,
|
207
266
|
id,
|
208
267
|
)
|
268
|
+
|
269
|
+
# append attachments to tooltip
|
270
|
+
if is_attachment:
|
271
|
+
files = data.get_attachment_names()
|
272
|
+
num = len(files)
|
273
|
+
files_str = ", ".join(files)
|
274
|
+
if len(files_str) > 40:
|
275
|
+
files_str = files_str[:40] + '...'
|
276
|
+
tooltip_str = trans("attachments.ctx.tooltip.list").format(num=num) + ": " + files_str
|
277
|
+
tooltip_text += "\n" + tooltip_str
|
278
|
+
|
209
279
|
item = Item(name, id)
|
210
280
|
item.id = id
|
211
281
|
item.dt = dt
|
212
282
|
item.isPinned = data.important
|
213
283
|
item.setData(tooltip_text, QtCore.Qt.ToolTipRole)
|
214
|
-
|
215
|
-
is_attachment = False
|
216
|
-
label = data.label
|
217
|
-
if data.important:
|
218
|
-
is_important = True
|
219
|
-
if data.additional_ctx and len(data.additional_ctx) > 0:
|
220
|
-
is_attachment = True
|
284
|
+
|
221
285
|
custom_data = {
|
222
286
|
"label": label,
|
223
287
|
"is_important": is_important,
|
224
288
|
"is_attachment": is_attachment,
|
289
|
+
"in_group": in_group,
|
225
290
|
}
|
226
291
|
item.setData(custom_data, QtCore.Qt.ItemDataRole.UserRole)
|
227
292
|
item.setData(name)
|
228
293
|
return item
|
229
294
|
|
230
|
-
def build_date_section(self, dt: str) -> SectionItem:
|
295
|
+
def build_date_section(self, dt: str, group: bool = False) -> SectionItem:
|
231
296
|
"""
|
232
297
|
Build date section
|
233
298
|
|
234
299
|
:param dt: date section string
|
300
|
+
:param group: is group
|
235
301
|
:return: SectionItem
|
236
302
|
"""
|
237
|
-
|
303
|
+
item = SectionItem(dt, group=group)
|
304
|
+
# item.setToolTip(dt)
|
305
|
+
return item
|
238
306
|
|
239
307
|
def convert_date(self, timestamp: int) -> str:
|
240
308
|
"""
|