diff --git a/omnivore/framework/actions.py b/omnivore/framework/actions.py index 230f1d67..2c2ca5b2 100644 --- a/omnivore/framework/actions.py +++ b/omnivore/framework/actions.py @@ -13,7 +13,7 @@ from .enthought_api_replacements import EditorAction, NameChangeAction, TaskDynamicSubmenuGroup, ApplicationDynamicSubmenuGroup from omnivore.framework.about import AboutDialog from omnivore.utils.file_guess import FileGuess -from omnivore.utils.wx.dialogs import get_file_dialog_wildcard +from omnivore.utils.wx.dialogs import get_file_dialog_wildcard, prompt_for_dec from omnivore.utils.wx.error_logger import show_logging_frame from omnivore.templates import iter_templates @@ -72,6 +72,22 @@ def _get_tooltip(self): return u'Open a new %s' % self.name +class NewEmptyFileAction(EditorAction): + """Create a blank file by specifying the size in bytes + """ + name = "Blank File" + tooltip = "Create a blank file" + + def perform(self, event=None): + e = self.active_editor + val = prompt_for_dec(e.window.control, 'Enter file size in bytes', 'New Blank File', 256) + val = 256 + if val is not None and val > 0: + uri = "blank://%d" % val + guess = FileGuess(uri) + self.task.new(guess) + + class NewFileGroup(Group): """ A menu for creating a new file for each type of task """ @@ -105,6 +121,8 @@ def _get_items(self): items.append((name, ActionItem(action=action))) items.sort() items = [i[1] for i in items] + blank = NewEmptyFileAction(task_id=task_id) + items[0:0] = [ActionItem(action=blank)] return items def _rebuild(self): diff --git a/omnivore/framework/filesystem.py b/omnivore/framework/filesystem.py index 422fc229..631dd9b1 100644 --- a/omnivore/framework/filesystem.py +++ b/omnivore/framework/filesystem.py @@ -1,6 +1,7 @@ import os import sys import datetime +from cStringIO import StringIO from pyface.api import ImageResource @@ -263,6 +264,69 @@ def get_fs(cls, registry, fs_name, fs_name_params, fs_path, writeable, create_d return fs, resourcename +class BlankFS(FS): + """Simple fs to read files from the template directories. + + """ + + _meta = {'read_only': True, + 'network': False} + + def __init__(self, url): + self.root_url = url + + def open(self, path, mode='r', buffering=-1, encoding=None, errors=None, newline=None, line_buffering=False, **kwargs): + + if '+' in mode or 'w' in mode or 'a' in mode: + raise UnsupportedError('write') + + log.debug("BlankFS: loading %s" % path) + try: + size = int(path) + except ValueError, e: + raise fs.errors.ResourceNotFoundError(path, details="Invalid size. %s" % e) + fh = StringIO('\0' * size) + return fh + + def exists(self, path): + return True + + def isdir(self, path): + return False + + def isfile(self, path): + return True + + def listdir(self, path="./", + wildcard=None, + full=False, + absolute=False, + dirs_only=False, + files_only=False): + return [] + + def getinfo(self, path): + info['size'] = int(path) + return info + + +class BlankOpener(Opener): + names = ['blank'] + desc = """Simple filesystem to return empty files of requested size + +examples: +* blank:256 (opens a 256 file, filled with zeros) +* blank:65536 (opens a 64K file, filled with zeros) + """ + + @classmethod + def get_fs(cls, registry, fs_name, fs_name_params, fs_path, writeable, create_dir): + dirname = "/" + resourcename = fs_path + fs = BlankFS(dirname) + return fs, resourcename + + def init_filesystems(): wx.FileSystem.AddHandler(WxAboutFileSystemHandler()) wx.FileSystem.AddHandler(wx.MemoryFSHandler()) @@ -284,6 +348,7 @@ def init_filesystems(): def init_about_filesystem(): opener.add(AboutOpener) opener.add(TemplateOpener) + opener.add(BlankOpener) for name, text in about.iteritems(): url = "about://%s" % name fh = opener.open(url, "wb")