Compare commits

...

5 Commits

9 changed files with 113 additions and 20 deletions

View File

@ -36,14 +36,14 @@ def add_record(action, *args, **kwargs):
revision = next_revision() revision = next_revision()
data = [revision, timestamp, [action] + list(args)] data = [revision, timestamp, [action] + list(args)]
data = json.dumps(data, ensure_ascii=False) data = json.dumps(data, ensure_ascii=False).encode('utf-8')
path = changelog_path() path = changelog_path()
if os.path.exists(path): if os.path.exists(path):
mode = 'a' mode = 'ab'
state.changelog_size = os.path.getsize(path) state.changelog_size = os.path.getsize(path)
else: else:
mode = 'w' mode = 'wb'
state.changelog_size = 0 state.changelog_size = 0
makefolder(path) makefolder(path)
with open(path, mode) as fd: with open(path, mode) as fd:

View File

@ -311,13 +311,20 @@ class Item(db.Model):
def delete(self, commit=True): def delete(self, commit=True):
Sort.query.filter_by(item_id=self.id).delete() Sort.query.filter_by(item_id=self.id).delete()
Find.query.filter_by(item_id=self.id).delete()
if state.downloads and self.id in state.downloads.transfers: if state.downloads and self.id in state.downloads.transfers:
del state.downloads.transfers[self.id] del state.downloads.transfers[self.id]
state.db.session.delete(self) state.db.session.delete(self)
icons.clear('cover:%s' % self.id)
icons.clear('preview:%s' % self.id)
if commit: if commit:
state.db.session.commit() state.db.session.commit()
icons.clear('cover:%s' % self.id)
icons.clear('preview:%s' % self.id)
def remove_annotations(self):
from annotation.models import Annotation
for a in Annotation.query.filter_by(item_id=self.id, user_id=state.user()):
a.add_record('removeannotation')
a.delete()
meta_keys = ( meta_keys = (
'author', 'author',
@ -562,6 +569,7 @@ class Item(db.Model):
state.db.session.add(self) state.db.session.add(self)
def remove_file(self): def remove_file(self):
folders = set()
for f in self.files.all(): for f in self.files.all():
path = f.fullpath() path = f.fullpath()
if os.path.exists(path): if os.path.exists(path):
@ -569,10 +577,12 @@ class Item(db.Model):
try: try:
os.chmod(path, mode) os.chmod(path, mode)
os.unlink(path) os.unlink(path)
remove_empty_folders(os.path.dirname(path)) folders.add(os.path.dirname(path))
except: except:
pass pass
state.db.session.delete(f) state.db.session.delete(f)
for folder in folders:
remove_empty_folders(folder)
user = state.user() user = state.user()
if user in self.users: if user in self.users:
self.users.remove(user) self.users.remove(user)
@ -589,6 +599,7 @@ class Item(db.Model):
if self.id in state.downloads.transfers: if self.id in state.downloads.transfers:
del state.downloads.transfers[self.id] del state.downloads.transfers[self.id]
add_record('removeitem', self.id) add_record('removeitem', self.id)
self.remove_annotations()
class Sort(db.Model): class Sort(db.Model):
__tablename__ = 'sort' __tablename__ = 'sort'

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import codecs
import json import json
import os import os
import time import time
@ -52,7 +53,7 @@ class Peer(object):
def apply_log(self): def apply_log(self):
changes = [] changes = []
if os.path.exists(self._logpath): if os.path.exists(self._logpath):
with open(self._logpath) as fd: with codecs.open(self._logpath, 'r', encoding='utf-8') as fd:
for line in fd: for line in fd:
if line: if line:
try: try:

View File

@ -70,6 +70,8 @@ class Node(Thread):
else: else:
if not self._q.qsize(): if not self._q.qsize():
time.sleep(5) time.sleep(5)
else:
time.sleep(0.1)
self.queue(action[0], *action[1]) self.queue(action[0], *action[1])
else: else:
logger.debug('unknown action %s', action) logger.debug('unknown action %s', action)
@ -83,7 +85,8 @@ class Node(Thread):
self._q.put('ping') self._q.put('ping')
def queue(self, action, *args): def queue(self, action, *args):
logger.debug('queue node action %s->%s%s', self.user_id, action, args) if DEBUG_NODES:
logger.debug('queue node action %s->%s%s', self.user_id, action, args)
self._q.put([action, args]) self._q.put([action, args])
def _call(self, action, *args): def _call(self, action, *args):

View File

@ -45,7 +45,7 @@ AvoidDiskWrites 1
Log notice stdout Log notice stdout
SocksPort 9830 SocksPort 9830
ControlPort 9831 ControlPort 9831
CookieAuthentication 1 #CookieAuthentication 1
'''.strip()) '''.strip())
tor_data = os.path.join(settings.data_path, 'TorData') tor_data = os.path.join(settings.data_path, 'TorData')
if sys.platform == 'win32': if sys.platform == 'win32':
@ -103,6 +103,7 @@ DirReqStatistics 0
for line in self.p.stdout: for line in self.p.stdout:
self._status.append(line) self._status.append(line)
logger.debug(line) logger.debug(line)
self.p.communicate()
time.sleep(0.5) time.sleep(0.5)
self.p = None self.p = None

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
oml.ui.annotationPanel = function() { oml.ui.annotationPanel = function(options, self) {
self = self || {};
var ui = oml.user.ui; var ui = oml.user.ui;
var ui = oml.user.ui; var ui = oml.user.ui;
@ -29,14 +30,15 @@ oml.ui.annotationPanel = function() {
click: function() { click: function() {
var $annotation = oml.$ui.annotationFolder.find('.OMLAnnotation.selected') var $annotation = oml.$ui.annotationFolder.find('.OMLAnnotation.selected')
$annotation.length && $annotation.delete() $annotation.length && $annotation.delete()
$deleteQuote.options({disabled: true}) that.updateSelection()
} }
}).appendTo($bar); }).appendTo($bar);
var $menuButton = Ox.MenuButton({ var $menuButton = Ox.MenuButton({
items: [ items: [
{id: 'addAnnotation', title: 'Add Annotation', disabled: true}, {id: 'addAnnotation', title: 'Add Annotation', disabled: true, keyboard: 'return'},
{id: 'removeAnnotation', title: 'Remove Annotation', disabled: true}, {id: 'removeAnnotation', title: 'Remove Annotation', disabled: true, keyboard: 'delete'},
{id: 'removeAnnotations', title: 'Remove All Annotation', disabled: true},
{}, {},
{id: 'show', title: Ox._('Show Annotations'), disabled: true}, {id: 'show', title: Ox._('Show Annotations'), disabled: true},
{group: 'showAnnotationUsers', min: 1, max: 1, items: [ {group: 'showAnnotationUsers', min: 1, max: 1, items: [
@ -82,6 +84,14 @@ oml.ui.annotationPanel = function() {
}, function(result) { }, function(result) {
oml.ui.exportAnnotationsDialog(result.data).open() oml.ui.exportAnnotationsDialog(result.data).open()
}) })
} else if (id =='addAnnotation') {
oml.$ui.viewer.postMessage('addAnnotation', {})
} else if (id =='removeAnnotation') {
var $annotation = oml.$ui.annotationFolder.find('.OMLAnnotation.selected')
$annotation.length && $annotation.delete()
that.updateSelection()
} else if (id =='removeAnnotations') {
oml.ui.removeAnnotationsDialog().open()
} else { } else {
console.log('click', id, data) console.log('click', id, data)
} }
@ -113,16 +123,18 @@ oml.ui.annotationPanel = function() {
} }
], ],
orientation: 'vertical' orientation: 'vertical'
}, self).update({
hasAnnotations: function() {
$menuButton[self.options.hasAnnotations ? 'enableItem' : 'disableItem']('removeAnnotations')
}
}); });
that.updateSelection = function(selection) { that.updateSelection = function(selection) {
$addQuote.options({
disabled: !selection
})
var $annotation = oml.$ui.annotationFolder.find('.OMLAnnotation.selected') var $annotation = oml.$ui.annotationFolder.find('.OMLAnnotation.selected')
$deleteQuote.options({ $addQuote.options({disabled: !selection})
disabled: !$annotation.length $deleteQuote.options({disabled: !$annotation.length})
}) $menuButton[selection ? 'enableItem' : 'disableItem']('addAnnotation')
$menuButton[$annotation.length ? 'enableItem' : 'disableItem']('removeAnnotation')
} }
return that; return that;

View File

@ -0,0 +1,48 @@
'use strict';
oml.ui.removeAnnotationsDialog = function() {
var ui = oml.user.ui,
annotations = oml.$ui.viewer.getAnnotations().filter(function(a) {
return a.user == oml.user.id
}),
annotationsName = Ox._(annotations.length == 1 ? 'Annotation' : 'Annotations'),
theseAnnotationsName = annotations.length == 1
? Ox._('this annotation')
: Ox._('these {0} annotations', [Ox.formatNumber(annotations.length)]),
that = oml.ui.confirmDialog({
buttons: [
Ox.Button({
style: 'squared',
title: Ox._('No, Keep {0}', [annotationsName])
}),
Ox.Button({
style: 'squared',
title: Ox._('Yes, Delete {0}', [annotationsName])
})
],
content: Ox._(
'Are you sure that you want to permanently delete {0}?',
[theseAnnotationsName]
),
title: Ox._('Delete {0}', [annotationsName])
}, function() {
Ox.serialForEach(annotations, function(a, index, annotations, next) {
oml.api.removeAnnotation({
item: ui.item,
annotation: a.id
}, function(result) {
next()
})
}, function() {
Ox.Request.clearCache();
oml.$ui.viewer.renderAnnotations(true);
})
});
return that;
};

View File

@ -111,6 +111,7 @@ oml.ui.viewer = function() {
if (save !== false) { if (save !== false) {
oml.api.addAnnotation(a) oml.api.addAnnotation(a)
} }
data.user = a.user || oml.user.id
data.notes = data.notes || []; data.notes = data.notes || [];
annotations.push(data); annotations.push(data);
} }
@ -157,9 +158,13 @@ oml.ui.viewer = function() {
oml.$ui.annotationFolder.append($annotation); oml.$ui.annotationFolder.append($annotation);
$annotation.annotate(); $annotation.annotate();
oml.$ui.annotationPanel.updateSelection(false) oml.$ui.annotationPanel.updateSelection(false)
oml.$ui.annotationPanel.options({hasAnnotations: true})
} else if (event == 'removeAnnotation') { } else if (event == 'removeAnnotation') {
oml.$ui.annotationFolder.find('#a-' + data.id).remove() oml.$ui.annotationFolder.find('#a-' + data.id).remove()
data.id && removeAnnotation(data.id) data.id && removeAnnotation(data.id)
oml.$ui.annotationPanel.options({hasAnnotations: annotations.filter(function(a) {
return a.user == oml.user.id
}).length > 0})
} else if (event == 'selectAnnotation') { } else if (event == 'selectAnnotation') {
if (data.id) { if (data.id) {
var $annotation = oml.$ui.annotationFolder.find('#a-' + data.id) var $annotation = oml.$ui.annotationFolder.find('#a-' + data.id)
@ -196,7 +201,7 @@ oml.ui.viewer = function() {
that.getAnnotations = function() { that.getAnnotations = function() {
return annotations; return annotations;
} }
that.renderAnnotations = function() { that.renderAnnotations = function(load=false) {
var sortKey = ui.sortAnnotations var sortKey = ui.sortAnnotations
if (sortKey == 'date') { if (sortKey == 'date') {
sortKey = 'created' sortKey = 'created'
@ -207,9 +212,15 @@ oml.ui.viewer = function() {
if (sortKey == 'quote') { if (sortKey == 'quote') {
sortKey = 'text' sortKey = 'text'
} }
if (load) {
loadAnnotations(function() {
that.renderAnnotations()
})
}
annotations = Ox.sortBy(annotations, sortKey) annotations = Ox.sortBy(annotations, sortKey)
oml.$ui.annotationFolder.empty(); oml.$ui.annotationFolder.empty();
var visibleAnnotations = []; var visibleAnnotations = [];
var hasAnnotations = false;
annotations.forEach(function(data) { annotations.forEach(function(data) {
//that.postMessage('removeAnnotation', {id: data.id}) //that.postMessage('removeAnnotation', {id: data.id})
if (ui.showAnnotationUsers == 'all' || data.user == oml.user.id) { if (ui.showAnnotationUsers == 'all' || data.user == oml.user.id) {
@ -217,7 +228,11 @@ oml.ui.viewer = function() {
oml.$ui.annotationFolder.append($annotation); oml.$ui.annotationFolder.append($annotation);
visibleAnnotations.push(data) visibleAnnotations.push(data)
} }
if (data.user == oml.user.id) {
hasAnnotations = true
}
}) })
oml.$ui.annotationPanel.options({hasAnnotations: hasAnnotations})
// fixme: trigger loaded event from reader instead? // fixme: trigger loaded event from reader instead?
setTimeout(function() { setTimeout(function() {
that.postMessage('addAnnotations', { that.postMessage('addAnnotations', {
@ -225,6 +240,7 @@ oml.ui.viewer = function() {
replace: true replace: true
}) })
}, 500) }, 500)
} }
return that.updateElement(); return that.updateElement();
}; };

View File

@ -58,6 +58,7 @@
"preferencesPanel.js", "preferencesPanel.js",
"previewButton.js", "previewButton.js",
"previewDialog.js", "previewDialog.js",
"removeAnnotations.js",
"resetUIDialog.js", "resetUIDialog.js",
"rightPanel.js", "rightPanel.js",
"sectionButtons.js", "sectionButtons.js",