Commit d27c1bcf authored by Kai Willadsen's avatar Kai Willadsen

Merge branch 'dirdiff.fast_insert' into 'master'

dirdiff.fast_insert - make append faster avoiding use of set_value

See merge request !22
parents 4350aaae 5750d705
......@@ -243,7 +243,7 @@ COL_EMBLEM, COL_EMBLEM_SECONDARY, COL_SIZE, COL_TIME, COL_PERMS, COL_END = \
class DirDiffTreeStore(tree.DiffTreeStore):
def __init__(self, ntree):
super().__init__(ntree, [str, str, object, object, object])
super().__init__(ntree, [str, str, int, float, int])
class CanonicalListing:
......@@ -759,7 +759,11 @@ class DirDiff(MeldDoc, Component):
try:
entries = os.listdir(root)
except OSError as err:
self.model.add_error(it, err.strerror, pane)
self.model.add_error(it, err.strerror, pane, {
COL_TIME: -1.0,
COL_SIZE: -1,
COL_PERMS: -1
})
differences = True
continue
......@@ -782,7 +786,11 @@ class DirDiff(MeldDoc, Component):
# Covers certain unreadable symlink cases; see bgo#585895
except OSError as err:
error_string = e + err.strerror
self.model.add_error(it, error_string, pane)
self.model.add_error(it, error_string, pane, {
COL_TIME: -1.0,
COL_SIZE: -1,
COL_PERMS: -1
})
continue
if stat.S_ISLNK(s.st_mode):
......@@ -803,7 +811,11 @@ class DirDiff(MeldDoc, Component):
error_string = e + ": Dangling symlink"
else:
error_string = e + err.strerror
self.model.add_error(it, error_string, pane)
self.model.add_error(it, error_string, pane, {
COL_TIME: -1.0,
COL_SIZE: -1,
COL_PERMS: -1
})
differences = True
elif stat.S_ISREG(s.st_mode):
files.add(pane, e)
......@@ -1437,23 +1449,29 @@ class DirDiff(MeldDoc, Component):
isdir = [os.path.isdir(files[j]) for j in range(self.model.ntree)]
for j in range(self.model.ntree):
column_index = functools.partial(self.model.column_index, pane=j)
if stats[j]:
self.model.set_path_state(
it, j, state, isdir[j], display_text=name_overrides[j])
emblem = EMBLEM_NEW if j in newest else None
self.model.set_value(it, column_index(COL_EMBLEM), emblem)
link_emblem = EMBLEM_SYMLINK if j in symlinks else None
self.model.set_value(
it, column_index(COL_EMBLEM_SECONDARY), link_emblem)
self.model.set_value(it, column_index(COL_TIME), times[j])
self.model.set_value(it, column_index(COL_SIZE), sizes[j])
self.model.set_value(it, column_index(COL_PERMS), perms[j])
self.model.unsafe_set(it, j, {
COL_EMBLEM: emblem,
COL_EMBLEM_SECONDARY: link_emblem,
COL_TIME: times[j],
COL_SIZE: sizes[j],
COL_PERMS: perms[j]
})
else:
# TODO: More consistent state setting here would let us avoid
# pyobjects for column types by avoiding None use.
self.model.set_path_state(
it, j, tree.STATE_NONEXIST, any(isdir))
# SET time, size and perms to -1 since None of GInt is 0
# TODO: change it to math.nan some day
# https://gitlab.gnome.org/GNOME/glib/issues/183
self.model.unsafe_set(it, j, {
COL_TIME: -1.0,
COL_SIZE: -1,
COL_PERMS: -1
})
return different
def popup_in_pane(self, pane, event):
......
......@@ -16,8 +16,10 @@
import os
from gi.module import get_introspection_module
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Pango
from meld.misc import colour_lookup_with_fallback
......@@ -29,6 +31,13 @@ from meld.vc._vc import ( # noqa: F401
STATE_NOCHANGE, STATE_NONE, STATE_NONEXIST, STATE_NORMAL, STATE_REMOVED,
)
_GIGtk = None
try:
_GIGtk = get_introspection_module('Gtk')
except Exception:
pass
COL_PATH, COL_STATE, COL_TEXT, COL_ICON, COL_TINT, COL_FG, COL_STYLE, \
COL_WEIGHT, COL_STRIKE, COL_END = list(range(10))
......@@ -43,6 +52,10 @@ class DiffTreeStore(SearchableTreeStore):
for col_type in (COL_TYPES + tuple(types)):
full_types.extend([col_type] * ntree)
super().__init__(*full_types)
self._none_of_cols = {
col_num: GObject.Value(col_type, None)
for col_num, col_type in enumerate(full_types)
}
self.ntree = ntree
self._setup_default_styles()
......@@ -114,22 +127,23 @@ class DiffTreeStore(SearchableTreeStore):
return self.ntree * col + pane
def add_entries(self, parent, names):
child = self.append(parent)
it = self.append(parent)
for pane, path in enumerate(names):
self.set_value(child, self.column_index(COL_PATH, pane), path)
return child
self.unsafe_set(it, pane, {COL_PATH: path})
return it
def add_empty(self, parent, text="empty folder"):
it = self.append(parent)
for pane in range(self.ntree):
self.set_value(it, self.column_index(COL_PATH, pane), None)
self.set_state(it, pane, STATE_EMPTY, text)
return it
def add_error(self, parent, msg, pane):
def add_error(self, parent, msg, pane, defaults={}):
it = self.append(parent)
key_values = {COL_STATE: str(STATE_ERROR)}
key_values.update(defaults)
for i in range(self.ntree):
self.set_value(it, self.column_index(COL_STATE, i),
str(STATE_ERROR))
self.unsafe_set(it, i, key_values)
self.set_state(it, pane, STATE_ERROR, msg)
def set_path_state(self, it, pane, state, isdir=0, display_text=None):
......@@ -139,19 +153,19 @@ class DiffTreeStore(SearchableTreeStore):
self.set_state(it, pane, state, display_text, isdir)
def set_state(self, it, pane, state, label, isdir=0):
col_idx = self.column_index
icon = self.icon_details[state][1 if isdir else 0]
tint = self.icon_details[state][3 if isdir else 2]
self.set_value(it, col_idx(COL_STATE, pane), str(state))
self.set_value(it, col_idx(COL_TEXT, pane), label)
self.set_value(it, col_idx(COL_ICON, pane), icon)
self.set_value(it, col_idx(COL_TINT, pane), tint)
fg, style, weight, strike = self.text_attributes[state]
self.set_value(it, col_idx(COL_FG, pane), fg)
self.set_value(it, col_idx(COL_STYLE, pane), style)
self.set_value(it, col_idx(COL_WEIGHT, pane), weight)
self.set_value(it, col_idx(COL_STRIKE, pane), strike)
self.unsafe_set(it, pane, {
COL_STATE: str(state),
COL_TEXT: label,
COL_ICON: icon,
COL_TINT: tint,
COL_FG: fg,
COL_STYLE: style,
COL_WEIGHT: weight,
COL_STRIKE: strike
})
def get_state(self, it, pane):
state_idx = self.column_index(COL_STATE, pane)
......@@ -178,6 +192,32 @@ class DiffTreeStore(SearchableTreeStore):
if state in states:
yield it
def unsafe_set(self, treeiter, pane, keys_values):
""" This must be fastest than super.set,
at the cost that may crash the application if you don't
know what your're passing here.
ie: pass treeiter or column as None crash meld
treeiter: Gtk.TreeIter
keys_values: dict<column, value>
column: Int col index
value: Str (UTF-8), Int, Float, Double, Boolean, None or GObject
return None
"""
safe_keys_values = {
self.column_index(col, pane):
val if val is not None
else self._none_of_cols.get(self.column_index(col, pane))
for col, val in keys_values.items()
}
if _GIGtk and treeiter:
columns = [col for col in safe_keys_values.keys()]
values = [val for val in safe_keys_values.values()]
_GIGtk.TreeStore.set(self, treeiter, columns, values)
else:
self.set(treeiter, safe_keys_values)
def treeview_search_cb(model, column, key, it, data):
# If the key contains a path separator, search the whole path,
......
......@@ -31,7 +31,7 @@ class CellRendererDate(Gtk.CellRendererText):
def set_timestamp(self, value):
if value == self.get_timestamp():
return
if value is None:
if value == -1.0:
time_str = ''
else:
mod_datetime = datetime.datetime.fromtimestamp(value)
......@@ -40,7 +40,7 @@ class CellRendererDate(Gtk.CellRendererText):
self._datetime = value
timestamp = GObject.Property(
type=object,
type=float,
nick="Unix timestamp to display",
getter=get_timestamp,
setter=set_timestamp,
......@@ -57,7 +57,7 @@ class CellRendererByteSize(Gtk.CellRendererText):
def set_bytesize(self, value):
if value == self.get_bytesize():
return
if value is None:
if value == -1:
byte_str = ''
else:
suffixes = (
......@@ -74,7 +74,7 @@ class CellRendererByteSize(Gtk.CellRendererText):
self._bytesize = value
bytesize = GObject.Property(
type=object,
type=int,
nick="Byte size to display",
getter=get_bytesize,
setter=set_bytesize,
......@@ -91,7 +91,7 @@ class CellRendererFileMode(Gtk.CellRendererText):
def set_file_mode(self, value):
if value == self.get_file_mode():
return
if value is None:
if value == -1.0:
mode_str = ''
else:
perms = []
......@@ -104,7 +104,7 @@ class CellRendererFileMode(Gtk.CellRendererText):
self._file_mode = value
file_mode = GObject.Property(
type=object,
type=int,
nick="Byte size to display",
getter=get_file_mode,
setter=set_file_mode,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment