sistemate alcune cose nella schermata di editing del profilo, modificato report differenze aggiungendo file agiunti e tolti nella tabella
This commit is contained in:
parent
0901887a3e
commit
ea1d31b82e
@ -143,8 +143,8 @@
|
|||||||
{
|
{
|
||||||
"name": "DSP",
|
"name": "DSP",
|
||||||
"paths": [
|
"paths": [
|
||||||
"C:\\__temp\\Metrics\\attuale\\REP\\Projects\\DSP",
|
"C:\\src\\____GitProjects\\SXXXXXXX_PyUcc\\__UCC\\Metrics\\_25_11\\REP\\Projects\\DSP",
|
||||||
"C:\\__temp\\Metrics\\attuale\\REP\\Projects\\DspAlgorithms"
|
"C:\\src\\____GitProjects\\SXXXXXXX_PyUcc\\__UCC\\Metrics\\_25_11\\REP\\Projects\\DspAlgorithms"
|
||||||
],
|
],
|
||||||
"languages": [
|
"languages": [
|
||||||
"C",
|
"C",
|
||||||
|
|||||||
@ -62,6 +62,8 @@ class ProfileManager(tk.Toplevel):
|
|||||||
self.title("Profile Manager")
|
self.title("Profile Manager")
|
||||||
self.geometry("1100x700")
|
self.geometry("1100x700")
|
||||||
self.on_change = on_change
|
self.on_change = on_change
|
||||||
|
# currently loaded profile dict (or None for new)
|
||||||
|
self._loaded_profile = None
|
||||||
|
|
||||||
self.profiles = profiles_cfg.load_profiles()
|
self.profiles = profiles_cfg.load_profiles()
|
||||||
|
|
||||||
@ -97,7 +99,7 @@ class ProfileManager(tk.Toplevel):
|
|||||||
self.ext_frame.grid(row=0, column=1, sticky="nsew")
|
self.ext_frame.grid(row=0, column=1, sticky="nsew")
|
||||||
|
|
||||||
# Paths listbox + scrollbar inside its frame
|
# Paths listbox + scrollbar inside its frame
|
||||||
self.paths_listbox = tk.Listbox(self.paths_frame, height=12)
|
self.paths_listbox = tk.Listbox(self.paths_frame, height=12, exportselection=False)
|
||||||
self.paths_listbox.grid(row=0, column=0, sticky="nsew")
|
self.paths_listbox.grid(row=0, column=0, sticky="nsew")
|
||||||
paths_vsb = ttk.Scrollbar(
|
paths_vsb = ttk.Scrollbar(
|
||||||
self.paths_frame, orient="vertical", command=self.paths_listbox.yview
|
self.paths_frame, orient="vertical", command=self.paths_listbox.yview
|
||||||
@ -141,7 +143,7 @@ class ProfileManager(tk.Toplevel):
|
|||||||
).grid(row=1, column=1, padx=6, pady=4)
|
).grid(row=1, column=1, padx=6, pady=4)
|
||||||
|
|
||||||
# Extensions listbox + scrollbar inside its frame
|
# Extensions listbox + scrollbar inside its frame
|
||||||
self.ext_listbox = tk.Listbox(self.ext_frame, selectmode="extended", height=12)
|
self.ext_listbox = tk.Listbox(self.ext_frame, selectmode="extended", height=12, exportselection=False)
|
||||||
self.ext_listbox.grid(row=0, column=0, sticky="nsew")
|
self.ext_listbox.grid(row=0, column=0, sticky="nsew")
|
||||||
ext_vsb = ttk.Scrollbar(
|
ext_vsb = ttk.Scrollbar(
|
||||||
self.ext_frame, orient="vertical", command=self.ext_listbox.yview
|
self.ext_frame, orient="vertical", command=self.ext_listbox.yview
|
||||||
@ -215,10 +217,16 @@ class ProfileManager(tk.Toplevel):
|
|||||||
ttk.Button(btn_frame, text="Delete", command=self._delete).grid(
|
ttk.Button(btn_frame, text="Delete", command=self._delete).grid(
|
||||||
row=0, column=3, padx=4
|
row=0, column=3, padx=4
|
||||||
)
|
)
|
||||||
ttk.Button(btn_frame, text="Close", command=self.destroy).grid(
|
ttk.Button(btn_frame, text="Close", command=self._on_close).grid(
|
||||||
row=0, column=4, padx=4
|
row=0, column=4, padx=4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# handle window close (X) the same way as Close button
|
||||||
|
try:
|
||||||
|
self.protocol("WM_DELETE_WINDOW", self._on_close)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
right.columnconfigure(1, weight=1)
|
right.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
# If no profiles exist, prefill form with sensible defaults (widgets are ready)
|
# If no profiles exist, prefill form with sensible defaults (widgets are ready)
|
||||||
@ -247,36 +255,25 @@ class ProfileManager(tk.Toplevel):
|
|||||||
if f:
|
if f:
|
||||||
self._insert_path_display("end", str(Path(f)))
|
self._insert_path_display("end", str(Path(f)))
|
||||||
|
|
||||||
def _populate_ext_listbox(self):
|
def _insert_path_display(self, index, path_str: str):
|
||||||
# Populate extension listbox with LANGUAGE_EXTENSIONS entries
|
# choose a prefix depending on whether path is dir/file/unknown
|
||||||
try:
|
p = Path(path_str)
|
||||||
from ..config.languages import LANGUAGE_EXTENSIONS
|
if p.exists():
|
||||||
except Exception:
|
prefix = "[D] " if p.is_dir() else "[F] "
|
||||||
return
|
else:
|
||||||
self.ext_listbox.delete(0, "end")
|
prefix = "[?] "
|
||||||
keys = sorted(LANGUAGE_EXTENSIONS.keys(), key=lambda s: s.lower())
|
display = f"{prefix}{path_str}"
|
||||||
for k in keys:
|
self.paths_listbox.insert(index, display)
|
||||||
exts = LANGUAGE_EXTENSIONS.get(k) or []
|
|
||||||
exts_label = f" ({', '.join(exts)})" if exts else ""
|
|
||||||
self.ext_listbox.insert("end", f"{k}{exts_label}")
|
|
||||||
|
|
||||||
def _clear_ext_selection(self):
|
def _strip_display_prefix(self, display_text: str) -> str:
|
||||||
self.ext_listbox.selection_clear(0, "end")
|
# remove known prefixes like [D] , [F] , [?] if present
|
||||||
|
if (
|
||||||
def _edit_selected_path(self):
|
display_text.startswith("[D] ")
|
||||||
sel = self.paths_listbox.curselection()
|
or display_text.startswith("[F] ")
|
||||||
if not sel:
|
or display_text.startswith("[?] ")
|
||||||
return
|
):
|
||||||
idx = sel[0]
|
return display_text[4:]
|
||||||
current = self.paths_listbox.get(idx)
|
return display_text
|
||||||
# strip prefix for editing
|
|
||||||
stripped = self._strip_display_prefix(current)
|
|
||||||
new = simpledialog.askstring(
|
|
||||||
"Edit Path", "Path:", initialvalue=stripped, parent=self
|
|
||||||
)
|
|
||||||
if new:
|
|
||||||
self.paths_listbox.delete(idx)
|
|
||||||
self._insert_path_display(idx, new)
|
|
||||||
|
|
||||||
def _remove_selected_path(self):
|
def _remove_selected_path(self):
|
||||||
sel = list(self.paths_listbox.curselection())
|
sel = list(self.paths_listbox.curselection())
|
||||||
@ -319,25 +316,107 @@ class ProfileManager(tk.Toplevel):
|
|||||||
for i in [min(size - 1, x + 1) for x in sel]:
|
for i in [min(size - 1, x + 1) for x in sel]:
|
||||||
self.paths_listbox.selection_set(i)
|
self.paths_listbox.selection_set(i)
|
||||||
|
|
||||||
def _insert_path_display(self, index, path_str: str):
|
def _populate_ext_listbox(self):
|
||||||
# choose a prefix depending on whether path is dir/file/unknown
|
# Populate extension listbox with LANGUAGE_EXTENSIONS entries
|
||||||
p = Path(path_str)
|
try:
|
||||||
if p.exists():
|
from ..config.languages import LANGUAGE_EXTENSIONS
|
||||||
prefix = "[D] " if p.is_dir() else "[F] "
|
except Exception:
|
||||||
else:
|
return
|
||||||
prefix = "[?] "
|
self.ext_listbox.delete(0, "end")
|
||||||
display = f"{prefix}{path_str}"
|
keys = sorted(LANGUAGE_EXTENSIONS.keys(), key=lambda s: s.lower())
|
||||||
self.paths_listbox.insert(index, display)
|
for k in keys:
|
||||||
|
exts = LANGUAGE_EXTENSIONS.get(k) or []
|
||||||
|
exts_label = f" ({', '.join(exts)})" if exts else ""
|
||||||
|
self.ext_listbox.insert("end", f"{k}{exts_label}")
|
||||||
|
|
||||||
def _strip_display_prefix(self, display_text: str) -> str:
|
def _clear_ext_selection(self):
|
||||||
# remove known prefixes like [D] , [F] , [?] if present
|
self.ext_listbox.selection_clear(0, "end")
|
||||||
if (
|
|
||||||
display_text.startswith("[D] ")
|
def _edit_selected_path(self):
|
||||||
or display_text.startswith("[F] ")
|
sel = self.paths_listbox.curselection()
|
||||||
or display_text.startswith("[?] ")
|
if not sel:
|
||||||
):
|
return
|
||||||
return display_text[4:]
|
idx = sel[0]
|
||||||
return display_text
|
current = self.paths_listbox.get(idx)
|
||||||
|
# strip prefix for editing
|
||||||
|
stripped = self._strip_display_prefix(current)
|
||||||
|
new = self._ask_edit_path(stripped)
|
||||||
|
if new:
|
||||||
|
self.paths_listbox.delete(idx)
|
||||||
|
self._insert_path_display(idx, new)
|
||||||
|
|
||||||
|
def _ask_edit_path(self, initial: str) -> str:
|
||||||
|
"""Open a small modal dialog with a larger entry widget for editing paths.
|
||||||
|
|
||||||
|
Returns the edited string, or None if cancelled.
|
||||||
|
"""
|
||||||
|
dlg = tk.Toplevel(self)
|
||||||
|
dlg.title("Edit Path")
|
||||||
|
dlg.transient(self)
|
||||||
|
dlg.grab_set()
|
||||||
|
|
||||||
|
frm = ttk.Frame(dlg)
|
||||||
|
frm.grid(row=0, column=0, padx=8, pady=8, sticky="nsew")
|
||||||
|
ttk.Label(frm, text="Path:").grid(row=0, column=0, columnspan=2, sticky="w")
|
||||||
|
val = tk.StringVar(value=initial)
|
||||||
|
entry = ttk.Entry(frm, textvariable=val, width=90)
|
||||||
|
entry.grid(row=1, column=0, sticky="ew", pady=(6, 0))
|
||||||
|
|
||||||
|
def _on_browse():
|
||||||
|
d = filedialog.askdirectory(parent=dlg)
|
||||||
|
if d:
|
||||||
|
val.set(str(Path(d)))
|
||||||
|
entry.focus_set()
|
||||||
|
entry.selection_range(0, 'end')
|
||||||
|
|
||||||
|
browse_btn = ttk.Button(frm, text="Browse...", command=_on_browse)
|
||||||
|
browse_btn.grid(row=1, column=1, padx=(6, 0), pady=(6, 0))
|
||||||
|
|
||||||
|
btns = ttk.Frame(frm)
|
||||||
|
btns.grid(row=2, column=0, columnspan=2, pady=(10, 0), sticky="e")
|
||||||
|
|
||||||
|
ok_pressed = {"ok": False}
|
||||||
|
|
||||||
|
def _on_ok():
|
||||||
|
ok_pressed["ok"] = True
|
||||||
|
try:
|
||||||
|
dlg.destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _on_cancel():
|
||||||
|
try:
|
||||||
|
dlg.destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
ttk.Button(btns, text="OK", command=_on_ok).grid(row=0, column=0, padx=6)
|
||||||
|
ttk.Button(btns, text="Cancel", command=_on_cancel).grid(row=0, column=1)
|
||||||
|
|
||||||
|
frm.columnconfigure(0, weight=1)
|
||||||
|
# center dialog above parent (ProfileManager)
|
||||||
|
try:
|
||||||
|
dlg.update_idletasks()
|
||||||
|
pwx = self.winfo_rootx()
|
||||||
|
pwy = self.winfo_rooty()
|
||||||
|
pww = self.winfo_width()
|
||||||
|
pwh = self.winfo_height()
|
||||||
|
dw = dlg.winfo_width()
|
||||||
|
dh = dlg.winfo_height()
|
||||||
|
cx = pwx + max(0, (pww - dw) // 2)
|
||||||
|
cy = pwy + max(0, (pwh - dh) // 2)
|
||||||
|
dlg.geometry(f"+{cx}+{cy}")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
entry.focus_set()
|
||||||
|
entry.selection_range(0, 'end')
|
||||||
|
self.wait_window(dlg)
|
||||||
|
|
||||||
|
if ok_pressed["ok"]:
|
||||||
|
return val.get().strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_paths_from_listbox(self) -> List[str]:
|
def _get_paths_from_listbox(self) -> List[str]:
|
||||||
out = []
|
out = []
|
||||||
@ -356,6 +435,8 @@ class ProfileManager(tk.Toplevel):
|
|||||||
|
|
||||||
def _load_profile(self, pr):
|
def _load_profile(self, pr):
|
||||||
self.name_var.set(pr.get("name", ""))
|
self.name_var.set(pr.get("name", ""))
|
||||||
|
# remember loaded profile so we can detect unsaved changes on close
|
||||||
|
self._loaded_profile = dict(pr)
|
||||||
# Load only new-style 'paths' list (no legacy compatibility)
|
# Load only new-style 'paths' list (no legacy compatibility)
|
||||||
self.paths_listbox.delete(0, "end")
|
self.paths_listbox.delete(0, "end")
|
||||||
paths = pr.get("paths") or []
|
paths = pr.get("paths") or []
|
||||||
@ -396,6 +477,8 @@ class ProfileManager(tk.Toplevel):
|
|||||||
self.ignore_text.delete("1.0", "end")
|
self.ignore_text.delete("1.0", "end")
|
||||||
# insert the DEFAULT_IGNORES joined by commas
|
# insert the DEFAULT_IGNORES joined by commas
|
||||||
self.ignore_text.insert("1.0", ",".join(self.DEFAULT_IGNORES))
|
self.ignore_text.insert("1.0", ",".join(self.DEFAULT_IGNORES))
|
||||||
|
# new form — no loaded profile
|
||||||
|
self._loaded_profile = None
|
||||||
|
|
||||||
def _apply_default_ignores(self):
|
def _apply_default_ignores(self):
|
||||||
"""Merge current ignore patterns with the DEFAULT_IGNORES and
|
"""Merge current ignore patterns with the DEFAULT_IGNORES and
|
||||||
@ -472,6 +555,11 @@ class ProfileManager(tk.Toplevel):
|
|||||||
messagebox.showinfo("Saved", f"Profile '{name}' saved.")
|
messagebox.showinfo("Saved", f"Profile '{name}' saved.")
|
||||||
if self.on_change:
|
if self.on_change:
|
||||||
self.on_change()
|
self.on_change()
|
||||||
|
# mark this as the currently loaded profile
|
||||||
|
try:
|
||||||
|
self._loaded_profile = dict(profile)
|
||||||
|
except Exception:
|
||||||
|
self._loaded_profile = None
|
||||||
|
|
||||||
def _delete(self):
|
def _delete(self):
|
||||||
name = self.name_var.get().strip()
|
name = self.name_var.get().strip()
|
||||||
@ -487,3 +575,71 @@ class ProfileManager(tk.Toplevel):
|
|||||||
self._new()
|
self._new()
|
||||||
if self.on_change:
|
if self.on_change:
|
||||||
self.on_change()
|
self.on_change()
|
||||||
|
self._loaded_profile = None
|
||||||
|
|
||||||
|
def _on_close(self):
|
||||||
|
"""Handle window close: if form differs from loaded profile, ask to save."""
|
||||||
|
# build current form representation
|
||||||
|
try:
|
||||||
|
cur_name = self.name_var.get().strip()
|
||||||
|
cur_paths = self._get_paths_from_listbox()
|
||||||
|
cur_langs = []
|
||||||
|
try:
|
||||||
|
sel = [self.ext_listbox.get(i) for i in self.ext_listbox.curselection()]
|
||||||
|
for s in sel:
|
||||||
|
lang_name = s.split(" (", 1)[0]
|
||||||
|
if lang_name and lang_name not in cur_langs:
|
||||||
|
cur_langs.append(lang_name)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
raw_custom = self.custom_text.get("1.0", "end").strip()
|
||||||
|
raw_custom = raw_custom.replace("\n", ",")
|
||||||
|
custom = [c.strip() for c in raw_custom.split(",") if c.strip()]
|
||||||
|
cur_langs.extend([c for c in custom if c])
|
||||||
|
raw_ignore = self.ignore_text.get("1.0", "end").strip()
|
||||||
|
raw_ignore = raw_ignore.replace("\n", ",")
|
||||||
|
cur_ignore = [s.strip() for s in raw_ignore.split(",") if s.strip()]
|
||||||
|
cur_profile = {
|
||||||
|
"name": cur_name,
|
||||||
|
"paths": cur_paths,
|
||||||
|
"languages": cur_langs,
|
||||||
|
"ignore": cur_ignore,
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
cur_profile = None
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
if self._loaded_profile is None and any([v for v in (cur_name, cur_paths, cur_langs, cur_ignore) if v]):
|
||||||
|
changed = True
|
||||||
|
elif self._loaded_profile is not None and cur_profile is not None:
|
||||||
|
# compare simple dicts
|
||||||
|
# note: do not attempt deep-normalization beyond this
|
||||||
|
if (
|
||||||
|
self._loaded_profile.get("name") != cur_profile.get("name")
|
||||||
|
or self._loaded_profile.get("paths") != cur_profile.get("paths")
|
||||||
|
or self._loaded_profile.get("languages") != cur_profile.get("languages")
|
||||||
|
or self._loaded_profile.get("ignore") != cur_profile.get("ignore")
|
||||||
|
):
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
ans = messagebox.askyesnocancel(
|
||||||
|
"Unsaved Changes", "Save changes to profile before closing?"
|
||||||
|
)
|
||||||
|
# True => save, False => discard and close, None => cancel
|
||||||
|
if ans is None:
|
||||||
|
return
|
||||||
|
if ans:
|
||||||
|
try:
|
||||||
|
self._save()
|
||||||
|
except Exception:
|
||||||
|
# if save fails, don't close
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.destroy()
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
super().destroy()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|||||||
@ -101,7 +101,26 @@ class TopBar(ttk.Frame):
|
|||||||
|
|
||||||
def _open_manager(self):
|
def _open_manager(self):
|
||||||
def _refresh():
|
def _refresh():
|
||||||
|
# remember current selection, reload profiles and restore selection
|
||||||
|
cur = self.profile_var.get()
|
||||||
self._load_profiles()
|
self._load_profiles()
|
||||||
|
vals = list(self.profile_cb["values"]) if self.profile_cb["values"] else []
|
||||||
|
if cur and cur in vals:
|
||||||
|
# keep same selection and refresh derived UI
|
||||||
|
self.profile_var.set(cur)
|
||||||
|
self._on_profile_selected()
|
||||||
|
elif vals:
|
||||||
|
# if there is at least one profile, ensure UI reflects a valid selection
|
||||||
|
# keep existing selection if already set, otherwise pick first
|
||||||
|
if not self.profile_var.get():
|
||||||
|
self.profile_var.set(vals[0])
|
||||||
|
self._on_profile_selected()
|
||||||
|
else:
|
||||||
|
# no profiles available
|
||||||
|
self.profile_var.set("")
|
||||||
|
self.current_profile = None
|
||||||
|
self.path_var.set("")
|
||||||
|
self.project_type_var.set("-")
|
||||||
|
|
||||||
pm = ProfileManager(self.master, on_change=_refresh)
|
pm = ProfileManager(self.master, on_change=_refresh)
|
||||||
pm.grab_set()
|
pm.grab_set()
|
||||||
|
|||||||
@ -316,8 +316,49 @@ def generate_differ_report(result, profile_config, baseline_id, output_path):
|
|||||||
m = counts.get("modified", 0)
|
m = counts.get("modified", 0)
|
||||||
u = counts.get("unmodified", 0)
|
u = counts.get("unmodified", 0)
|
||||||
|
|
||||||
cd = pair.get("countings_delta") or {}
|
# Prefer explicit deltas computed by the differ, but if missing
|
||||||
md = pair.get("metrics_delta") or {}
|
# (e.g. added or deleted files where only one side exists) fall
|
||||||
|
# back to using the current or baseline values so the compact
|
||||||
|
# table shows meaningful numbers for new/deleted files.
|
||||||
|
cd = pair.get("countings_delta")
|
||||||
|
if cd is None:
|
||||||
|
cur_cnt = pair.get("current_countings") or {}
|
||||||
|
base_cnt = pair.get("baseline_countings") or {}
|
||||||
|
if cur_cnt and not base_cnt:
|
||||||
|
cd = {
|
||||||
|
"physical_lines": cur_cnt.get("physical_lines", 0),
|
||||||
|
"code_lines": cur_cnt.get("code_lines", 0),
|
||||||
|
"comment_lines": cur_cnt.get("comment_lines", 0),
|
||||||
|
"blank_lines": cur_cnt.get("blank_lines", 0),
|
||||||
|
}
|
||||||
|
elif base_cnt and not cur_cnt:
|
||||||
|
cd = {
|
||||||
|
"physical_lines": -base_cnt.get("physical_lines", 0),
|
||||||
|
"code_lines": -base_cnt.get("code_lines", 0),
|
||||||
|
"comment_lines": -base_cnt.get("comment_lines", 0),
|
||||||
|
"blank_lines": -base_cnt.get("blank_lines", 0),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
cd = {}
|
||||||
|
|
||||||
|
md = pair.get("metrics_delta")
|
||||||
|
if md is None:
|
||||||
|
cur_m = pair.get("current_metrics") or {}
|
||||||
|
base_m = pair.get("baseline_metrics") or {}
|
||||||
|
if cur_m and not base_m:
|
||||||
|
md = {
|
||||||
|
"func_count": cur_m.get("func_count", 0),
|
||||||
|
"avg_cc": cur_m.get("avg_cc", 0.0),
|
||||||
|
"mi": cur_m.get("mi", 0.0),
|
||||||
|
}
|
||||||
|
elif base_m and not cur_m:
|
||||||
|
md = {
|
||||||
|
"func_count": -base_m.get("func_count", 0),
|
||||||
|
"avg_cc": -base_m.get("avg_cc", 0.0),
|
||||||
|
"mi": -base_m.get("mi", 0.0),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
md = {}
|
||||||
|
|
||||||
def fmt_int(v):
|
def fmt_int(v):
|
||||||
try:
|
try:
|
||||||
|
|||||||
6
todo.md
6
todo.md
@ -28,4 +28,8 @@
|
|||||||
- [x] colorare la tabella
|
- [x] colorare la tabella
|
||||||
- [x] salvare il file delle diff in automatico
|
- [x] salvare il file delle diff in automatico
|
||||||
- [x] mettere le hint per spiegare i vari parametri cosa sono
|
- [x] mettere le hint per spiegare i vari parametri cosa sono
|
||||||
- [x] ordinare le righe selezionando la colonna sia in ordine screscente che descrescente
|
- [x] ordinare le righe selezionando la colonna sia in ordine screscente che descrescente
|
||||||
|
- [ ] aggiornare profilo percorso quando premo su salva
|
||||||
|
- [x] non perdere la selezione sulle estensioni quando modifico il profilo
|
||||||
|
- [ ] verificare con dsp 10 e 11 le differenze con quelle di UCC intorno ai 70000 linee di codice 708 linee di codice modificato
|
||||||
|
- [ ] verificare se i commenti vengo conteggiati oppure no, nei file c++, c, h ecc
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user