Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
suurjaak committed Jul 18, 2023
2 parents 50f8b29 + d8e8709 commit 3e4950a
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 101 deletions.
13 changes: 10 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
CHANGELOG
=========

5.5, 2023-07-17
---------------
- fix Bing-bot not being synced properly (issue #117)
- fix importing latest Skype export archives (issue #119)
- add config option to disable automatic update checks and downloads
- upgrade all dependency libraries in compiled binaries


5.4.1, 2023-01-02
-----------------
- fix v5.4 release binaries containing outdated code
- fix --version flag being ignored


Expand Down Expand Up @@ -78,7 +85,7 @@ CHANGELOG


4.8.1, 2021-08-05
---------------
-----------------
- fixed audio/video messages imported from live as simple file transfers (issue #102)


Expand Down Expand Up @@ -214,7 +221,7 @@ CHANGELOG


3.5.1c, 2015-12-21
---------------
------------------
- added support for updated Skype chat structure (issue #40)
- added "Remove by type" button to start page (issue #47)
- fixed escaping bolded words in search chat title and participants link
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,8 @@ scratch, by downloading all available history.
Skyperious can read chat history archives exported from Skype, and merge their
contents into an existing database, or create a new database from their contents.

(Skype export is available in Skype client v8.5 under
Settings -> Messaging -> Export chat history from Skype 7.x;
and in Skype web interface under My account -> Export files and chat history.
(Skype export is available in Skype web interface under
My account -> Export files and chat history.
The result is a `.tar` archive containing a `messages.json` file.)

HTML export can download shared photos and embed them in the resulting HTML,
Expand Down
5 changes: 2 additions & 3 deletions build/README for Windows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,8 @@ scratch, by downloading all available history.
Skyperious can read chat history archives exported from Skype, and merge their
contents into an existing database, or create a new database from their contents.

(Skype export is available in Skype client v8.5 under
Settings -> Messaging -> Export chat history from Skype 7.x;
and in Skype web interface under My account -> Export files and chat history.
(Skype export is available in Skype web interface under
My account -> Export files and chat history.
The result is a .tar archive containing a messages.json file.)

HTML export can download shared photos and embed them in the resulting HTML,
Expand Down
11 changes: 7 additions & 4 deletions src/skyperious/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@author Erki Suurjaak
@created 26.11.2011
@modified 02.01.2023
@modified 18.07.2023
------------------------------------------------------------------------------
"""
try: from ConfigParser import RawConfigParser # Py2
Expand All @@ -24,8 +24,8 @@

"""Program title, version number and version date."""
Title = "Skyperious"
Version = "5.4.1"
VersionDate = "02.01.2023"
Version = "5.5.dev7"
VersionDate = "18.07.2023"

if getattr(sys, "frozen", False):
# Running as a pyinstaller executable
Expand Down Expand Up @@ -149,9 +149,12 @@
"""Whether the program tray icon is used."""
TrayIconEnabled = True

"""Whether the program checks for updates every UpdateCheckInterval."""
"""Whether the program checks for updates every UpdateCheckInterval if UpdateCheckEnabled."""
UpdateCheckAutomatic = True

"""Whether the program supports automatic update check and download."""
UpdateCheckEnabled = True

"""Whether the program has been minimized and hidden."""
WindowIconized = False

Expand Down
14 changes: 10 additions & 4 deletions src/skyperious/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@author Erki Suurjaak
@created 13.01.2012
@modified 20.09.2022
@modified 17.07.2023
------------------------------------------------------------------------------
"""
import codecs
Expand Down Expand Up @@ -558,9 +558,9 @@ def __init__(self, filename, sheetname=None, autowrap=()):
# For calculating column widths
self._fonts = collections.defaultdict(lambda: FONT_XLSX)
self._fonts["bold"] = FONT_XLSX_BOLD
unit_width_default = self._fonts[None].getsize("0")[0]
unit_width_default = get_extent(self._fonts[None], "0")[0]
self._unit_widths = collections.defaultdict(lambda: unit_width_default)
self._unit_widths["bold"] = self._fonts["bold"].getsize("0")[0]
self._unit_widths["bold"] = get_extent(self._fonts["bold"], "0")[0]

if sheetname: # Create default sheet
self.add_sheet(sheetname)
Expand Down Expand Up @@ -645,7 +645,7 @@ def writerow(self, values, style=None, merge_cols=0, autowidth=True):
if isinstance(v, six.text_type)
else v.strftime("%Y-%m-%d %H:%M") if isinstance(v, datetime.datetime)
else v if isinstance(v, six.string_types) else str(v))
pixels = max(self._fonts[fmt_name].getsize(x)[0]
pixels = max(get_extent(self._fonts[fmt_name], x)[0]
for x in strval.split("\n"))
width = float(pixels) / self._unit_widths[fmt_name] + 1
if not merge_cols and width > self._col_widths[self._sheet.name][c]:
Expand All @@ -667,3 +667,9 @@ def close(self):
(conf.Title, datetime.datetime.now().strftime("%d.%m.%Y %H:%M")),
"author": "%s %s" % (conf.Title, conf.Version)})
self._workbook.close()


def get_extent(font, text):
"""Returns (width, height) for specified font and text."""
if hasattr(font, "getsize"): return font.getsize(text) # < PIL v10
if hasattr(font, "getbbox"): return font.getbbox(text)[2:] # >= PIL v10
20 changes: 13 additions & 7 deletions src/skyperious/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@author Erki Suurjaak
@created 26.11.2011
@modified 13.10.2022
@modified 17.07.2023
------------------------------------------------------------------------------
"""
import ast
Expand Down Expand Up @@ -525,7 +525,8 @@ def create_menu(self):
id2=wx.ID_FILE1 + conf.MaxRecentFiles)
if self.trayicon.IsAvailable():
menu_tray.Check(conf.TrayIconEnabled)
menu_autoupdate_check.Check(conf.UpdateCheckAutomatic)
menu_autoupdate_check.Check(conf.UpdateCheckEnabled and conf.UpdateCheckAutomatic)
menu_autoupdate_check.Enable(conf.UpdateCheckEnabled)

self.Bind(wx.EVT_MENU, self.on_new_blank, menu_new_blank)
if menu_new_live:
Expand Down Expand Up @@ -553,15 +554,15 @@ def update_check(self):
from last check has passed, and opens a dialog for upgrading
if new version available. Schedules a new check on due date.
"""
if self or not conf.UpdateCheckAutomatic: return
if not self or not conf.UpdateCheckEnabled or not conf.UpdateCheckAutomatic: return

interval = datetime.timedelta(days=conf.UpdateCheckInterval)
due_date = datetime.datetime.now() - interval
if not (conf.WindowIconized or support.update_window) \
and conf.LastUpdateCheck < due_date.strftime("%Y%m%d"):
and (not conf.LastUpdateCheck or conf.LastUpdateCheck < due_date.strftime("%Y%m%d")):
callback = lambda resp: self.on_check_update_callback(resp, False)
support.check_newest_version(callback)
elif not support.update_window:
elif not support.update_window and conf.LastUpdateCheck:
try:
dt = datetime.datetime.strptime(conf.LastUpdateCheck, "%Y%m%d")
interval = (dt + interval) - datetime.datetime.now()
Expand Down Expand Up @@ -930,7 +931,12 @@ def on_check_update_callback(self, check_result, full_response=True):
MAX = 1000
changes = changes[:MAX] + ".." if len(changes) > MAX else changes
guibase.status("New %s version %s available.", conf.Title, version)
if wx.OK == wx.MessageBox(
if not conf.UpdateCheckEnabled: wx.MessageBox(
"Newer version (%s) available. You are currently on version %s.%s" %
(version, conf.Version, "\n\n%s\n" % changes),
"Update information", wx.OK | wx.ICON_INFORMATION
)
elif wx.OK == wx.MessageBox(
"Newer version (%s) available. You are currently on "
"version %s.%s\nDownload and install %s %s?" %
(version, conf.Version, "\n\n%s\n" % changes,
Expand Down Expand Up @@ -6441,7 +6447,7 @@ def populate_chat_statistics(self):
img, imgkey = self.imagecache.get(("chat", self.chat["id"])), ("chat", self.chat["id"])
try:
raw = skypedata.fix_image_raw(pic) if pic and not img else None
img = img or wx.Image(io.BytesIO(raw.encode("latin1")))
img = img or (wx.Image(io.BytesIO(raw.encode("latin1"))) if raw else None)
except Exception:
logger.exception("Error loading image for %s.", self.chat["title_long_lc"])
if img:
Expand Down
112 changes: 53 additions & 59 deletions src/skyperious/lib/wx_accel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
- wx.TextCtrl control focused, all text selected
- wx.RadioButton control focused, value selected
- wx.Control control focused
- wx.ToolBar tool event is called, if the tool shorthelp includes a
parseable shortcut key like (Alt-S)
- wx.ToolBar tool event is called, if the tool label contains shortcut
or if the tool shorthelp includes a parseable shortcut key
like "(Alt-S)"
- wx.ToggleButton ToggleButton handler called
Uses primitive heuristic analysis to detect connected label-control pairs:
Expand All @@ -30,7 +31,7 @@
@author Erki Suurjaak
@created 19.11.2011
@modified 26.03.2022
@modified 18.07.2023
------------------------------------------------------------------------------
"""
import functools
Expand Down Expand Up @@ -87,6 +88,42 @@ def UpdateAccelerators(self, use_heuristics=True):



def parse_label(text):
"""Returns first suitable ampersanded shortcut key from text, in lowercase, or None."""
for part in filter(len, text.split("&")[1:]):
key = part[0].lower() # Find usable ampersand, preceding a valid character
if key > " ": return key
return None


def parse_shortcuts(ctrl):
"""
Parses the shortcut keys from the control label, if any.
If wx.ToolBar, parses tool labels, and shorthelps for explicit shortcut texts.
@return {key: control or toolbar tool ID}
"""
result = {}
if isinstance(ctrl, wx.ToolBar):
for i in range(ctrl.GetToolsCount()):
tool = ctrl.GetToolByPos(i)
if not tool: continue # for i
key = parse_label(tool.Label)
if key:
result.setdefault(key, tool.Id)
if DEBUG: print("Parsed '%s' in tool label '%s'." % (key, tool.Label))
parts = re.split("\\(Alt-(.)\\)", tool.ShortHelp, maxsplit=1)
if len(parts) > 1:
result.setdefault(parts[1].lower(), tool.Id)
# wx.TextCtrl.Label is the same as its value, so must not use that
elif hasattr(ctrl, "Label") and not isinstance(ctrl, wx.TextCtrl):
key = parse_label(ctrl.Label)
if key:
result[key] = ctrl.Id
if DEBUG: print("Parsed '%s' in label '%s'." % (key, ctrl.Label))
return result


def collect_shortcuts(control, use_heuristics=True):
"""
Returns a map of detected shortcut keys and target controls under the
Expand All @@ -105,35 +142,6 @@ def collect_shortcuts(control, use_heuristics=True):
nameds = {} # collected controls with Name {name: control, }
statics = {} # collected StaticTexts with a shortcut {control: char, }

def parse_shortcuts(ctrl):
"""
Parses the shortcut keys from the control label, if any.
@return [keys]
"""
result = []
# wx.TextCtrl.Label is the same as its value, so must not use that
if isinstance(ctrl, wx.ToolBar):
for i in range(ctrl.GetToolsCount()):
tool = ctrl.GetToolByPos(i)
if not tool: continue # for i
text = ctrl.GetToolShortHelp(tool.GetId())
parts = re.split("\\(Alt-(.)\\)", text, maxsplit=1)
if len(parts) > 1:
result.append(parts[1].lower())
elif hasattr(ctrl, "Label") and not isinstance(ctrl, wx.TextCtrl):
for part in filter(len, ctrl.Label.split("&")[1:]):
# Labels have potentially multiple ampersands - find one that
# is usable (preceding a valid character. 32 and lower are
# spaces, punctuation, control characters, etc).
key = part[0].lower()
if ord(key) > 32:
result.append(key)
if DEBUG and key:
print("Parsed '%s' in label '%s'." % (key, ctrl.Label))
break # for part
return result


def collect_recurse(ctrl, result, nameds, statics):
"""
Expand All @@ -147,8 +155,7 @@ def collect_recurse(ctrl, result, nameds, statics):
for i in range(len(children)):
collect_recurse(children[i], result, nameds, statics)

keys = parse_shortcuts(ctrl)
for key in keys:
for key in parse_shortcuts(ctrl):
if isinstance(ctrl, wx.StaticText):
statics[ctrl] = key
else:
Expand Down Expand Up @@ -230,10 +237,9 @@ def collect_recurse(ctrl, result, nameds, statics):
if not target:
continue # for name, ctrl

key = (parse_shortcuts(ctrl) + [""]).pop(0)
key = next(iter(parse_shortcuts(ctrl)), "")
if DEBUG:
print("Name %s matches potential %s, key=%s." % (
name, basename, key))
print("Name %s matches potential %s, key=%s." % (name, basename, key))
if target not in result_values:
if target not in result.get(key, []):
result.setdefault(key, []).append((target, ctrl))
Expand All @@ -247,7 +253,6 @@ def collect_recurse(ctrl, result, nameds, statics):
return result



def accelerate(window, use_heuristics=True, skipclicklabels=None, accelerators=None):
"""
Assigns global keyboard shortcuts to all controls under the specified
Expand Down Expand Up @@ -280,8 +285,7 @@ def eventhandler(targets, key, shortcut_event):
@param shortcut_event menu event generated by the accelerator table
"""
if DEBUG:
print("Handling target %s" %
[(type(t), t.Id, t.Label) for t in targets])
print("Handling target %s" % [(type(t), t.Id, t.Label) for t in targets])
event, target = None, None
for target in targets:
if not target or not isinstance(target, wx.Control) \
Expand All @@ -308,23 +312,14 @@ def eventhandler(targets, key, shortcut_event):
else: target.Value = not target.Value
target.SetFocus()
elif isinstance(target, wx.ToolBar):
# Toolbar shortcuts are defined in their shorthelp texts
toolsmap, tb = dict(), target
for i in range(tb.GetToolsCount() + 1):
try:
tool = tb.FindToolForPosition(i * tb.ToolSize[0], 0)
toolsmap[repr(tool)] = tool
except Exception: pass # FindTool not implemented in GTK
for tool in filter(bool, toolsmap.values()):
id = tool.GetId()
text = tb.GetToolShortHelp(id)
parts = re.split("\\(Alt-(%s)\\)" % key, text,
maxsplit=1, flags=re.IGNORECASE)
if len(parts) > 1:
event = wx.CommandEvent(wx.EVT_TOOL.typeId, id)
event.SetEventObject(target)
target.ToggleTool(id, not target.GetToolState(id))
break # for tool
# Toolbar shortcuts are defined in tool labels and shorthelp texts
id_tool = parse_shortcuts(target).get(key)
if id_tool:
event = wx.CommandEvent(wx.EVT_TOOL.typeId, id_tool)
event.SetEventObject(target)
event.SetInt(not target.GetToolState(id_tool))
target.ToggleTool(id_tool, not target.GetToolState(id_tool))
break # for tool
else:
target.SetFocus()
if isinstance(target, wx.TextCtrl):
Expand Down Expand Up @@ -356,8 +351,7 @@ def eventhandler(targets, key, shortcut_event):
skipclicklabels.add(label)
if not key: continue # for key, targets
ctrls = [t[0] for t in targets]
if DEBUG: print("Binding %s to targets %s." %
(key, [type(t) for t in ctrls]))
if DEBUG: print("Binding %s to targets %s." % (key, [type(t) for t in ctrls]))
menu_item = dummy_menu.Append(wx.ID_ANY, "&%s" % key)
window.Bind(wx.EVT_MENU, functools.partial(eventhandler, ctrls, key),
menu_item)
Expand Down
Loading

0 comments on commit 3e4950a

Please sign in to comment.