Skip to content

Commit c56b367

Browse files
authored
search status overhaul, READMe contributing
- Added contributing section to README.md - Added number of files to compare - Duplicated now updates the search status (indicator and menu bar) - Globalised cache file from path and metadata from cache file operations - Added new delete cache after two hours option - Optimised cache deletion - Changed Inactive to Idle and Searching to Active - Reload files function now in FF_Menubar.py in prep. for adding it to duplicated - Fixed loaded search giving search from data instead of cache file path - Added warning, if cache is set to never - Added new linux arm build to the workflow
1 parent 7070916 commit c56b367

File tree

9 files changed

+271
-145
lines changed

9 files changed

+271
-145
lines changed

FF_Compare.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
# The window
2929
class CompareUi:
30-
def __init__(self, path_of_first_search, parent):
30+
def __init__(self, path_of_first_search, cache_file, parent):
3131
# Debug
3232
logging.info("Setting up the Compare_Window")
3333

@@ -70,7 +70,7 @@ def __init__(self, path_of_first_search, parent):
7070

7171
# Setting up the menu bar...
7272
menu_bar = FF_Menubar.MenuBar(parent=self.Compare_Window, window="compare",
73-
listbox=None)
73+
listbox=None, cache_file_path=cache_file)
7474
logging.debug("Done building MenuBar\n")
7575

7676
# Set up both list-boxes
@@ -110,13 +110,15 @@ def __init__(self, path_of_first_search, parent):
110110
# Labels
111111
# Added files
112112
self.added_files_label1, self.added_files_label2 = self.generate_title_label(
113-
text="Added Files", text2=path_of_first_search, color=FF_Files.GREEN_COLOR)
113+
text="Added Files", text2=path_of_first_search, color=FF_Files.GREEN_COLOR,
114+
length_of_list=len(compared_searches.files_only_in_first_search))
114115
self.Compare_Layout.addWidget(self.added_files_label1, 0, 0)
115116
self.Compare_Layout.addWidget(self.added_files_label2, 1, 0)
116117

117118
# Removed files
118119
self.removed_files_label1, self.removed_files_label2 = self.generate_title_label(
119-
text="Removed Files", text2=compared_searches.path_of_second_search[0], color=FF_Files.RED_COLOR)
120+
text="Removed Files", text2=compared_searches.path_of_second_search[0], color=FF_Files.RED_COLOR,
121+
length_of_list=len(compared_searches.files_only_in_second_search))
120122
self.Compare_Layout.addWidget(self.removed_files_label1, 0, 1)
121123
self.Compare_Layout.addWidget(self.removed_files_label2, 1, 1)
122124

@@ -160,7 +162,7 @@ def generate_button(self, text, command, icon=None):
160162
return button
161163

162164
# Function for generating the added / removed files labels
163-
def generate_title_label(self, text, text2, color) -> tuple[QLabel, QLabel]:
165+
def generate_title_label(self, text, text2, color, length_of_list) -> tuple[QLabel, QLabel]:
164166
# Label 1
165167
label1 = QLabel(self.Compare_Window)
166168

@@ -182,7 +184,7 @@ def generate_title_label(self, text, text2, color) -> tuple[QLabel, QLabel]:
182184

183185
# Shorten the text string to only include the first to the 30th
184186
# and the last ten character if the string is longer then 43 characters
185-
text2_shortened = f"Files only in:\n{FF_Files.display_path(text2)}"
187+
text2_shortened = f"{length_of_list} files only in:\n{FF_Files.display_path(text2)}"
186188
# Set the label to the shortened string
187189
label2.setText(text2_shortened)
188190

@@ -196,7 +198,7 @@ def generate_title_label(self, text, text2, color) -> tuple[QLabel, QLabel]:
196198

197199
# The engine
198200
class CompareSearches:
199-
def __init__(self, files_of_first_search: list, path_of_first_search, parent):
201+
def __init__(self, files_of_first_search: list, path_of_first_search, cache_file, parent):
200202
# Debug
201203
logging.debug("User pressed Compare Search")
202204

@@ -207,7 +209,7 @@ class SignalsClass(QObject):
207209

208210
self.signals = SignalsClass()
209211
# Connecting the signal to the user-interface class
210-
self.signals.finished.connect(lambda: CompareUi(path_of_first_search, parent))
212+
self.signals.finished.connect(lambda: CompareUi(path_of_first_search, cache_file, parent))
211213

212214
# Thread
213215
comparing_thread = QThreadPool(parent)

FF_Duplicated.py

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import logging
1313
import os
1414
from sys import platform
15+
from json import load
1516
from time import perf_counter, time, ctime
1617
import difflib
1718
import gc
@@ -25,6 +26,7 @@
2526
from PySide6.QtGui import QFont, QAction
2627

2728
# Projects Libraries
29+
import FF_Main_UI
2830
import FF_Menubar
2931
import FF_Additional_UI
3032
import FF_Files
@@ -36,7 +38,7 @@
3638

3739

3840
class DuplicatedSettings:
39-
def __init__(self, parent, search_path, matched_list):
41+
def __init__(self, parent, search_path, matched_list, cache_file):
4042
# Debug
4143
logging.info("Setting up Duplicated UI...")
4244

@@ -193,8 +195,16 @@ def store_value():
193195
self.button_box = QDialogButtonBox(parent=self.Duplicated_Settings)
194196
self.button_box.setStandardButtons(QDialogButtonBox.StandardButton.Cancel | QDialogButtonBox.StandardButton.Ok)
195197

198+
196199
# Connect events
197200
def start_duplicated():
201+
# Update search status label
202+
FF_Search.ACTIVE_SEARCH_THREADS += 1
203+
FF_Main_UI.MainWindow.update_search_status_label()
204+
# Initialising the ui logger
205+
self.ui_logger = FF_Main_UI.SearchUpdate(search_path)
206+
# Update the logger
207+
self.ui_logger.update("Finding duplicated files...")
198208

199209
# Default criteria
200210
criteria = {
@@ -210,7 +220,7 @@ def start_duplicated():
210220
class Events(QObject):
211221
finished = Signal()
212222

213-
finished_event_class = Events()
223+
self.event_class = Events()
214224

215225
if self.mode_selector_combobox.currentText() == self.duplicated_mode_display_name_dict["name"]:
216226
criteria["name"]["activated"] = True
@@ -219,17 +229,26 @@ class Events(QObject):
219229
elif self.mode_selector_combobox.currentText() == self.duplicated_mode_display_name_dict["content"]:
220230
criteria["content"]["activated"] = True
221231

232+
# Connect UI to finished signal
233+
self.event_class.finished.connect(
234+
lambda: DuplicatedUI(
235+
parent, search_path, criteria, duplicated_dict, duplicated_parent_file_path_dict, time_dict,
236+
cache_file))
237+
238+
self.event_class.finished.connect(
239+
lambda: logging.debug("Received finish finish signal"))
240+
241+
# Closing the menu bar logger
242+
self.event_class.finished.connect(self.ui_logger.close)
243+
222244
# Starting Thread
223245
QThreadPool(self.Duplicated_Settings).start(
224246
lambda: FindDuplicated(
225247
criteria=criteria,
226248
matched_list=matched_list,
227-
finished_signal=finished_event_class))
249+
signals=self.event_class))
250+
228251

229-
# Connect UI to finished signal
230-
finished_event_class.finished.connect(
231-
lambda: DuplicatedUI(
232-
parent, search_path, criteria, duplicated_dict, duplicated_parent_file_path_dict, time_dict))
233252

234253
# Launch search algorithm
235254
self.button_box.button(
@@ -286,7 +305,7 @@ def __init__(
286305
self,
287306
parent,
288307
match_path,
289-
criteria, matched_dict: dict, matched_parent_file_path_dict: dict, time_needed_dict: dict):
308+
criteria, matched_dict: dict, matched_parent_file_path_dict: dict, time_needed_dict: dict, cache_file: str):
290309
# Debug
291310
logging.info("Setting up Duplicated UI...")
292311
# Saving time
@@ -420,7 +439,8 @@ def __init__(
420439

421440
# Setup menu bar
422441
menu_bar = FF_Menubar.MenuBar(
423-
parent=self.Duplicated_Window, window="duplicated", listbox=self.Duplicated_Tree, search_path=match_path)
442+
parent=self.Duplicated_Window, window="duplicated", listbox=self.Duplicated_Tree, search_path=match_path,
443+
cache_file_path=cache_file)
424444

425445
# If item is double-clicked
426446
def open_double_clicked(item):
@@ -509,6 +529,11 @@ def show_time_stats():
509529
# Debug
510530
logging.debug("Displaying time stats.")
511531

532+
# Getting the creation time of the cache file which is stored separately
533+
with open(FF_Files.get_metadata_file_from_cache_file(cache_file)) as time_file:
534+
# Load time
535+
cache_created_time = ctime(load(time_file)["c_time"])
536+
512537
# Displaying infobox with time info
513538
FF_Additional_UI.PopUps.show_info_messagebox(
514539
"Time Stats",
@@ -520,20 +545,26 @@ def show_time_stats():
520545
f"Total: {round(time_needed_dict['time_after_building_ui'] - time_needed_dict['start_time'], 3)}s\n\n\n"
521546
""
522547
f"Timestamps:\n"
523-
f"Search opened: {ctime(time_stamp)}s",
524-
self.Duplicated_Window)
548+
f"Cache (basis for search results) created:\n{cache_created_time}\n"
549+
f"Window opened:\n{ctime(time_stamp)}s",
550+
large=True,
551+
parent=self.Duplicated_Window)
525552

526553
# Optimize label
527554
total_time = time_needed_dict["time_after_building_ui"] - time_needed_dict["start_time"]
528555
time_text.setText(f"Time needed: {round(total_time, 3)}s")
529556

557+
# Update search status label
558+
FF_Search.ACTIVE_SEARCH_THREADS -= 1
559+
FF_Main_UI.MainWindow.update_search_status_label()
560+
530561
# Collect garbage
531562
gc.collect()
532563

533564

534565
# Algorithms to find duplicated files
535566
class FindDuplicated:
536-
def __init__(self, criteria: dict, matched_list, finished_signal):
567+
def __init__(self, criteria: dict, matched_list, signals):
537568
# Debug
538569
logging.info("Searching for duplicated files...")
539570
logging.info(f"{criteria=}")
@@ -817,9 +848,10 @@ def __init__(self, criteria: dict, matched_list, finished_signal):
817848
# Finalize
818849
duplicated_parent_file_path_dict = duplicated_size_parent_file_path_dict
819850
duplicated_dict = duplicated_size_dict
820-
851+
# Debug
852+
logging.info("Finished grouping, launching UI...")
821853
# Launch UI
822-
finished_signal.finished.emit()
854+
signals.finished.emit()
823855

824856
gc.collect()
825857

FF_Files.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,15 @@ def path_to_cache_file(path, metadata=False):
139139
logging.fatal("Wrong arguments used with the convert_path_to_cache_file() function in FF_Files.py")
140140

141141

142+
# Takes a path to a cache file and returns the path to the metadata file
143+
def get_metadata_file_from_cache_file(cache_file):
144+
return CACHE_METADATA_FOLDER + (cache_file.removeprefix(CACHED_SEARCHES_FOLDER))
145+
146+
142147
# Test if Cache should be deleted
143148
def cache_test(is_launching):
144149
logging.debug("Testing if cache should be deleted..")
150+
allowed_time_difference = None
145151

146152
# Loading Settings File
147153
with open(os.path.join(FF_LIB_FOLDER, "Settings")) as settings_file:
@@ -154,43 +160,38 @@ def cache_test(is_launching):
154160
logging.debug("Deleting Cache!")
155161
remove_cache()
156162

163+
elif cache_settings.lower() == "after two hours":
164+
# Two hours are 7'200 seconds
165+
allowed_time_difference = 7200
166+
157167
# Deleting Cache after a Day
158168
elif cache_settings == "after a Day":
159-
160-
# Looping through every file in CACHED_SEARCHES_FOLDER and getting separately stored creation tie
161-
# Iterating through all files in the cache folder
162-
for file in os.listdir(CACHED_SEARCHES_FOLDER):
163-
try:
164-
with open(os.path.join(CACHE_METADATA_FOLDER, file)) as time_file:
165-
# Load creation time
166-
cache_created_time = load(time_file)["c_time"]
167-
except JSONDecodeError:
168-
continue
169-
170-
if cache_created_time < time() - SECONDS_OF_A_WEEK:
171-
logging.debug(f"Deleting Cache for dir: {file} because it's older than a week")
172-
os.remove(os.path.join(CACHED_SEARCHES_FOLDER, file))
169+
allowed_time_difference = SECONDS_OF_A_DAY
173170

174171
# Deleting Cache after a Week
175172
elif cache_settings == "after a Week":
173+
allowed_time_difference = SECONDS_OF_A_WEEK
174+
175+
# Skipping
176+
else:
177+
logging.debug("Skipping deleting...")
176178

179+
if cache_settings.lower() in ("after a Week", "after a Day", "after two hours"):
177180
# Looping through every file in CACHED_SEARCHES_FOLDER and getting separately stored creation tie
178181
# Iterating through all files in the cache folder
179182
for file in os.listdir(CACHED_SEARCHES_FOLDER):
180183
try:
181-
with open(os.path.join(CACHE_METADATA_FOLDER, file), "w") as time_file:
182-
# Load time
184+
with open(os.path.join(CACHE_METADATA_FOLDER, file)) as time_file:
185+
# Load creation time
183186
cache_created_time = load(time_file)["c_time"]
184187
except JSONDecodeError:
185188
continue
186189

187-
if cache_created_time < time() - SECONDS_OF_A_DAY:
188-
logging.debug(f"Deleting Cache for dir: {file} because it's older than a week")
190+
if cache_created_time < time() - allowed_time_difference:
191+
logging.debug(f"Deleting Cache for dir: {file} because it's older than the allowed time difference,"
192+
f" {allowed_time_difference=}sec.")
189193
os.remove(os.path.join(CACHED_SEARCHES_FOLDER, file))
190194

191-
# Skipping
192-
else:
193-
logging.debug("Skipping deleting...")
194195

195196
logging.debug("Finished Cache Testing!\n")
196197

FF_Main_UI.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ def export_filters(self):
10351035
return
10361036

10371037
# Debug
1038-
logging.info(f"Exporting all filters to {export_path}, with {FF_Files.FF_FILTER_VERSION = }...")
1038+
logging.info(f"Exporting all filters to {export_path}, with {FF_Files.FF_FILTER_VERSION=}...")
10391039
# Making user folder compatible
10401040
directory = self.edit_directory.text()
10411041
directory = directory.replace(FF_Files.USER_FOLDER, "USER_FOLDER")
@@ -1276,7 +1276,7 @@ def update_search_status_label(ui_building=False):
12761276
logging.debug(f"Updating search status label, active searches: {FF_Search.ACTIVE_SEARCH_THREADS}")
12771277
# If there are no active searches
12781278
if FF_Search.ACTIVE_SEARCH_THREADS == 0:
1279-
search_status_label.setText("Inactive")
1279+
search_status_label.setText("Idle")
12801280
search_status_label.setStyleSheet(f"color: {FF_Files.GREEN_COLOR};")
12811281
search_status_label.adjustSize()
12821282

@@ -1286,7 +1286,7 @@ def update_search_status_label(ui_building=False):
12861286

12871287
# If there are ongoing searches updating label
12881288
else:
1289-
search_status_label.setText(f"Searching ({FF_Search.ACTIVE_SEARCH_THREADS}) ...")
1289+
search_status_label.setText(f"Active ({FF_Search.ACTIVE_SEARCH_THREADS}) ...")
12901290
search_status_label.setStyleSheet(f"color: {FF_Files.RED_COLOR};")
12911291
search_status_label.adjustSize()
12921292

@@ -1326,4 +1326,5 @@ def close(self):
13261326
self.search_status_menu.removeAction(self.search_status)
13271327
self.search_status_menu.removeAction(self.search_path)
13281328

1329+
13291330
global menu_bar_icon_menu, search_status_menu, menu_bar_icon, search_status_label

0 commit comments

Comments
 (0)