Пример #1
0
def show_files_win32(path, files):
    """Takes a path to a directory and a list of filenames in that directory
    to display.

    Returns True on success.
    """

    assert os.name == "nt"

    import pywintypes
    from win32com.shell import shell

    assert is_fsnative(path)
    assert all(is_fsnative(f) for f in files)

    normalized_files = map(normalize_path, files)

    try:
        folder_pidl = shell.SHILCreateFromPath(path, 0)[0]
        desktop = shell.SHGetDesktopFolder()
        shell_folder = desktop.BindToObject(
            folder_pidl, None, shell.IID_IShellFolder)
        items = []
        for item in shell_folder:
            name = desktop.GetDisplayNameOf(item, 0)
            if normalize_path(name) in normalized_files:
                items.append(item)
        shell.SHOpenFolderAndSelectItems(folder_pidl, items, 0)
    except pywintypes.com_error:
        return False
    else:
        return True
Пример #2
0
def show_files_win32(path, files):
    """Takes a path to a directory and a list of filenames in that directory
    to display.

    Returns True on success.
    """

    assert os.name == "nt"

    import pywintypes
    from win32com.shell import shell

    assert is_fsnative(path)
    assert all(is_fsnative(f) for f in files)

    normalized_files = map(normalize_path, files)

    try:
        folder_pidl = shell.SHILCreateFromPath(path, 0)[0]
        desktop = shell.SHGetDesktopFolder()
        shell_folder = desktop.BindToObject(
            folder_pidl, None, shell.IID_IShellFolder)
        items = []
        for item in shell_folder:
            name = desktop.GetDisplayNameOf(item, 0)
            if normalize_path(name) in normalized_files:
                items.append(item)
        shell.SHOpenFolderAndSelectItems(folder_pidl, items, 0)
    except pywintypes.com_error:
        return False
    else:
        return True
Пример #3
0
 def test_uri_to_path(self):
     if os.name != "nt":
         path = uri_to_path("file:///home/piman/cr%21azy")
         self.assertTrue(is_fsnative(path))
         self.assertEqual(path, fsnative(u"/home/piman/cr!azy"))
     else:
         path = uri_to_path("file:///C:/foo")
         self.assertTrue(is_fsnative(path))
         self.assertEqual(path, fsnative(u"C:\\foo"))
Пример #4
0
 def test_lyric_filename(self):
     song = AudioFile()
     song["~filename"] = fsnative(u"filename")
     self.assertTrue(is_fsnative(song.lyric_filename))
     song["title"] = u"Title"
     song["artist"] = u"Artist"
     self.assertTrue(is_fsnative(song.lyric_filename))
     song["lyricist"] = u"Lyricist"
     self.assertTrue(is_fsnative(song.lyric_filename))
Пример #5
0
 def test_lyric_filename(self):
     song = AudioFile()
     song["~filename"] = fsnative(u"filename")
     self.assertTrue(is_fsnative(song.lyric_filename))
     song["title"] = u"Title"
     song["artist"] = u"Artist"
     self.assertTrue(is_fsnative(song.lyric_filename))
     song["lyricist"] = u"Lyricist"
     self.assertTrue(is_fsnative(song.lyric_filename))
Пример #6
0
 def test_uri2fsn(self):
     if os.name != "nt":
         path = uri2fsn("file:///home/piman/cr%21azy")
         self.assertTrue(is_fsnative(path))
         self.assertEqual(path, fsnative(u"/home/piman/cr!azy"))
     else:
         path = uri2fsn("file:///C:/foo")
         self.assertTrue(is_fsnative(path))
         self.assertEqual(path, fsnative(u"C:\\foo"))
Пример #7
0
    def test_conv(self):
        empty = fsnative(u"")

        v = self.c.filter(empty, fsnative(u"foobar baz"))
        self.failUnlessEqual(v, fsnative(u"foobar baz"))
        self.failUnless(is_fsnative(v))

        v = self.c.filter(empty, fsnative(u"Foobar.BAZ"))
        self.failUnlessEqual(v, fsnative(u"foobar.baz"))
        self.failUnless(is_fsnative(v))
    def test_conv(self):
        empty = fsnative(u"")

        v = self.c.filter(empty, fsnative(u"foobar baz"))
        self.failUnlessEqual(v, fsnative(u"foobar baz"))
        self.failUnless(is_fsnative(v))

        v = self.c.filter(empty, fsnative(u"Foobar.BAZ"))
        self.failUnlessEqual(v, fsnative(u"foobar.baz"))
        self.failUnless(is_fsnative(v))
Пример #9
0
    def test_main(self):
        v = fsnative(u"foo")
        self.assertTrue(is_fsnative(v))

        v2 = glib2fsnative(fsnative2glib(v))
        self.assertTrue(is_fsnative(v2))
        self.assertEqual(v, v2)

        v3 = bytes2fsnative(fsnative2bytes(v))
        self.assertTrue(is_fsnative(v3))
        self.assertEqual(v, v3)
Пример #10
0
    def test_main(self):
        v = fsnative(u"foo")
        self.assertTrue(is_fsnative(v))

        v2 = glib2fsnative(fsnative2glib(v))
        self.assertTrue(is_fsnative(v2))
        self.assertEqual(v, v2)

        v3 = bytes2fsnative(fsnative2bytes(v))
        self.assertTrue(is_fsnative(v3))
        self.assertEqual(v, v3)
Пример #11
0
    def test_cover_path(self):
        song = AudioFile({"musicbrainz_albumid": u"foobar"})
        song2 = AudioFile()

        # missing Soup
        if "lastfm-cover" in self.plugins:
            cls = self.plugins["lastfm-cover"].cls
            self.assertTrue(is_fsnative(cls(song).cover_path))
            self.assertTrue(is_fsnative(cls(song2).cover_path))

        # missing Soup
        if "musicbrainz-cover" in self.plugins:
            cls = self.plugins["musicbrainz-cover"].cls
            self.assertTrue(is_fsnative(cls(song).cover_path))
            self.assertTrue(is_fsnative(cls(song2).cover_path))
Пример #12
0
    def test_cover_path(self):
        song = AudioFile({"musicbrainz_albumid": u"foobar"})
        song2 = AudioFile()

        # missing Soup
        if "lastfm-cover" in self.plugins:
            cls = self.plugins["lastfm-cover"].cls
            self.assertTrue(is_fsnative(cls(song).cover_path))
            self.assertTrue(is_fsnative(cls(song2).cover_path))

        # missing Soup
        if "musicbrainz-cover" in self.plugins:
            cls = self.plugins["musicbrainz-cover"].cls
            self.assertTrue(is_fsnative(cls(song).cover_path))
            self.assertTrue(is_fsnative(cls(song2).cover_path))
 def test_conv(self):
     empty = fsnative(u"")
     in_ = fsnative(u"foo \u00c1 \u1234")
     out = fsnative(u"foo _ _")
     v = self.c.filter(empty, in_)
     self.failUnlessEqual(v, out)
     self.failUnless(is_fsnative(v))
Пример #14
0
 def test_conv(self):
     empty = fsnative(u"")
     test = fsnative(u"\u00c1 test")
     out = fsnative(u"A test")
     v = self.c.filter(empty, test)
     self.failUnlessEqual(v, out)
     self.failUnless(is_fsnative(v))
Пример #15
0
 def test_conv(self):
     empty = fsnative(u"")
     in_ = fsnative(u"foo \u00c1 \u1234")
     out = fsnative(u"foo _ _")
     v = self.c.filter(empty, in_)
     self.failUnlessEqual(v, out)
     self.failUnless(is_fsnative(v))
Пример #16
0
def get_thumbnail_from_file(fileobj, boundary):
    """Like get_thumbnail() but works with files that can't be reopened.

    This is needed on Windows where NamedTemporaryFile can't be reopened.

    Returns Pixbuf or None. Thread-safe.
    """

    assert fileobj

    try:
        path = fileobj.name
        assert is_fsnative(path), path
        return get_thumbnail(path, boundary)
    except GLib.GError:
        try:
            loader = GdkPixbuf.PixbufLoader()
            loader.set_size(*boundary)
            loader.write(fileobj.read())
            loader.close()
            fileobj.seek(0, 0)
            # can return None in case of partial data
            return loader.get_pixbuf()
        except (GLib.GError, EnvironmentError):
            pass
 def test_conv(self):
     empty = fsnative(u"")
     test = fsnative(u"\u00c1 test")
     out = fsnative(u"A test")
     v = self.c.filter(empty, test)
     self.failUnlessEqual(v, out)
     self.failUnless(is_fsnative(v))
Пример #18
0
def get_cache_info(path, boundary):
    """For an image at `path` return (cache_path, thumb_size)

    cache_path points to a potential cache file
    thumb size is either 128 or 256
    """

    assert is_fsnative(path)

    width, height = boundary

    if width <= ThumbSize.NORMAL and height <= ThumbSize.NORMAL:
        size_name = "normal"
        thumb_size = ThumbSize.NORMAL
    else:
        size_name = "large"
        thumb_size = ThumbSize.LARGE

    thumb_folder = get_thumbnail_folder()
    cache_dir = os.path.join(thumb_folder, size_name)

    uri = "file://" + pathname2url(path)
    thumb_name = hashlib.md5(uri).hexdigest() + ".png"
    thumb_path = os.path.join(cache_dir, thumb_name)

    return (thumb_path, thumb_size)
Пример #19
0
 def test_long_filename(s):
     if os.name == "nt":
         a = s.AudioFile({"title": "x" * 300, "~filename": u"C:\\f.mp3"})
         path = s._create(u'C:\\foobar\\ä<title>\\<title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255)
         path = s._create(u'äüö<title><title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 255)
     else:
         a = s.AudioFile({"title": "x" * 300, "~filename": "/f.mp3"})
         path = s._create(u'/foobar/ä<title>/<title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255)
         path = s._create(u'äüö<title><title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 255)
Пример #20
0
 def test_long_filename(s):
     if os.name == "nt":
         a = AudioFile({"title": "x" * 300, "~filename": u"C:\\f.mp3"})
         path = s._create(u'C:\\foobar\\ä<title>\\<title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255)
         path = s._create(u'äüö<title><title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 255)
     else:
         a = AudioFile({"title": "x" * 300, "~filename": "/f.mp3"})
         path = s._create(u'/foobar/ä<title>/<title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255)
         path = s._create(u'äüö<title><title>').format(a)
         assert is_fsnative(path)
         s.failUnlessEqual(len(path), 255)
Пример #21
0
def show_files_win32(path, files):
    """Takes a path to a directory and a list of filenames in that directory
    to display.

    Returns True on success.
    """

    assert os.name == "nt"
    assert is_fsnative(path)
    assert all(is_fsnative(f) for f in files)

    from quodlibet.util.windows import open_folder_and_select_items

    try:
        open_folder_and_select_items(path, files)
    except WindowsError:
        return False
    return True
Пример #22
0
    def sanitize(self, filename=None):
        """Fill in metadata defaults. Find ~mountpoint, ~#mtime, ~#filesize
        and ~#added. Check for null bytes in tags.

        Does not raise.
        """

        # Replace nulls with newlines, trimming zero-length segments
        for key, val in listitems(self):
            if isinstance(val, string_types) and '\0' in val:
                self[key] = '\n'.join(filter(lambda s: s, val.split('\0')))
            # Remove unnecessary defaults
            if key in NUMERIC_ZERO_DEFAULT and val == 0:
                del self[key]

        if filename:
            self["~filename"] = filename
        elif "~filename" not in self:
            raise ValueError("Unknown filename!")

        assert is_fsnative(self["~filename"])

        if self.is_file:
            self["~filename"] = normalize_path(self["~filename"],
                                               canonicalise=True)
            # Find mount point (terminating at "/" if necessary)
            head = self["~filename"]
            while "~mountpoint" not in self:
                head, tail = os.path.split(head)
                # Prevent infinite loop without a fully-qualified filename
                # (the unit tests use these).
                head = head or "/"
                if os.path.ismount(head):
                    self["~mountpoint"] = head
        else:
            self["~mountpoint"] = fsnative(u"/")

        # Fill in necessary values.
        self.setdefault("~#added", int(time.time()))

        # For efficiency, do a single stat here. See Issue 504
        try:
            stat = os.stat(self['~filename'])
            self["~#mtime"] = stat.st_mtime
            self["~#filesize"] = stat.st_size

            # Issue 342. This is a horrible approximation (due to headers) but
            # on FLACs, the most common case, this should be close enough
            if "~#bitrate" not in self:
                try:
                    # kbps = bytes * 8 / seconds / 1000
                    self["~#bitrate"] = int(stat.st_size / (self["~#length"] *
                                                            (1000 / 8)))
                except (KeyError, ZeroDivisionError):
                    pass
        except OSError:
            self["~#mtime"] = 0
Пример #23
0
    def sanitize(self, filename=None):
        """Fill in metadata defaults. Find ~mountpoint, ~#mtime, ~#filesize
        and ~#added. Check for null bytes in tags.

        Does not raise.
        """

        # Replace nulls with newlines, trimming zero-length segments
        for key, val in self.items():
            if isinstance(val, string_types) and '\0' in val:
                self[key] = '\n'.join(filter(lambda s: s, val.split('\0')))
            # Remove unnecessary defaults
            if key in INTERN_NUM_DEFAULT and val == 0:
                del self[key]

        if filename:
            self["~filename"] = filename
        elif "~filename" not in self:
            raise ValueError("Unknown filename!")

        assert is_fsnative(self["~filename"])

        if self.is_file:
            self["~filename"] = normalize_path(
                self["~filename"], canonicalise=True)
            # Find mount point (terminating at "/" if necessary)
            head = self["~filename"]
            while "~mountpoint" not in self:
                head, tail = os.path.split(head)
                # Prevent infinite loop without a fully-qualified filename
                # (the unit tests use these).
                head = head or "/"
                if os.path.ismount(head):
                    self["~mountpoint"] = head
        else:
            self["~mountpoint"] = fsnative(u"/")

        # Fill in necessary values.
        self.setdefault("~#added", int(time.time()))

        # For efficiency, do a single stat here. See Issue 504
        try:
            stat = os.stat(self['~filename'])
            self["~#mtime"] = stat.st_mtime
            self["~#filesize"] = stat.st_size

            # Issue 342. This is a horrible approximation (due to headers) but
            # on FLACs, the most common case, this should be close enough
            if "~#bitrate" not in self:
                try:
                    # kbps = bytes * 8 / seconds / 1000
                    self["~#bitrate"] = int(stat.st_size /
                                            (self["~#length"] * (1000 / 8)))
                except (KeyError, ZeroDivisionError):
                    pass
        except OSError:
            self["~#mtime"] = 0
Пример #24
0
    def test_roundtrip(self):
        if os.name == "nt":
            paths = [u"C:\\öäü.txt"]
        else:
            paths = [u"/öäü.txt", u"//foo/bar", u"///foo/bar"]

        for source in paths:
            path = uri2fsn(fsn2uri(fsnative(source)))
            self.assertTrue(is_fsnative(path))
            self.assertEqual(path, fsnative(source))
Пример #25
0
    def test_windows_path(self):
        if os.name != "nt":
            return

        win_path = u"C:\\SomeDir\xe4"
        uri = URI.frompath(win_path)
        self.assertEqual(uri, "file:///C:/SomeDir%C3%A4")
        self.assertTrue(uri.is_filename)
        self.assertTrue(is_fsnative(uri.filename))
        self.assertEqual(uri.filename, win_path)
Пример #26
0
    def test_roundtrip(self):
        if os.name == "nt":
            paths = [u"C:\\öäü.txt"]
        else:
            paths = [u"/öäü.txt", u"//foo/bar", u"///foo/bar"]

        for source in paths:
            path = uri_to_path(uri_from_path(fsnative(source)))
            self.assertTrue(is_fsnative(path))
            self.assertEqual(path, fsnative(source))
Пример #27
0
    def test_windows_path(self):
        if os.name != "nt":
            return

        win_path = u"C:\\SomeDir\xe4"
        uri = URI.frompath(win_path)
        self.assertEqual(uri, "file:///C:/SomeDir%C3%A4")
        self.assertTrue(uri.is_filename)
        self.assertTrue(is_fsnative(uri.filename))
        self.assertEqual(uri.filename, win_path)
Пример #28
0
    def test_ends_with_dots_or_spaces(self):
        empty = fsnative(u"")
        v = self.c.filter(empty, fsnative(u"foo. . "))
        self.failUnlessEqual(v, fsnative(u"foo. ._"))
        self.assertTrue(is_fsnative(v))

        if os.name == "nt":
            self.failUnlessEqual(self.c.filter(empty, u"foo. \\bar ."), u"foo._\\bar _")
        else:
            self.failUnlessEqual(self.c.filter(empty, u"foo. /bar ."), "foo._/bar _")
Пример #29
0
    def __getitem__(self, key):
        # we used to save them with the wrong type
        value = super(RemoteFile, self).__getitem__(key)
        if key in ("~filename", "~mountpoint") and not is_fsnative(value):
            if os.name == "nt":
                value = unicode(value)
            else:
                value = value.encode("utf-8")

        return value
Пример #30
0
 def test_main(self):
     try:
         1 / 0
     except:
         result = extract_tb(sys.exc_info()[2])
         self.assertTrue(isinstance(result, list))
         for fn, l, fu, text in result:
             self.assertTrue(is_fsnative(fn))
             self.assertTrue(isinstance(l, int))
             self.assertTrue(isinstance(fu, text_type))
             self.assertTrue(isinstance(text, text_type))
Пример #31
0
 def test_main(self):
     try:
         1 / 0
     except:
         result = extract_tb(sys.exc_info()[2])
         self.assertTrue(isinstance(result, list))
         for fn, l, fu, text in result:
             self.assertTrue(is_fsnative(fn))
             self.assertTrue(isinstance(l, int))
             self.assertTrue(isinstance(fu, text_type))
             self.assertTrue(isinstance(text, text_type))
Пример #32
0
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert is_fsnative(filename)

        mkdir(os.path.dirname(filename))

        with atomic_save(filename, ".tmp", "wb") as fileobj:
            self._config.write(fileobj)
Пример #33
0
    def test_ends_with_dots_or_spaces(self):
        empty = fsnative(u"")
        v = self.c.filter(empty, fsnative(u'foo. . '))
        self.failUnlessEqual(v, fsnative(u"foo. ._"))
        self.assertTrue(is_fsnative(v))

        if os.name == "nt":
            self.failUnlessEqual(
                self.c.filter(empty, u'foo. \\bar .'), u"foo._\\bar _")
        else:
            self.failUnlessEqual(
                self.c.filter(empty, u'foo. /bar .'), "foo._/bar _")
Пример #34
0
    def new(cls, dir_, base=_("New Playlist"), library=None):
        assert is_fsnative(dir_)

        if not (dir_ and os.path.realpath(dir_)):
            raise ValueError("Invalid playlist directory %r" % (dir_,))

        for i in range(1000):
            try:
                name = "%s %d" % (base, i) if i else base
                return FileBackedPlaylist(dir_, name, library, validate=True)
            except ValueError:
                pass
        raise ValueError("Couldn't create playlist of name '%s'" % base)
Пример #35
0
    def new(cls, dir_, base=_("New Playlist"), library=None):
        assert is_fsnative(dir_)

        if not (dir_ and os.path.realpath(dir_)):
            raise ValueError("Invalid playlist directory %r" % (dir_, ))

        for i in range(1000):
            try:
                name = "%s %d" % (base, i) if i else base
                return FileBackedPlaylist(dir_, name, library, validate=True)
            except ValueError:
                pass
        raise ValueError("Couldn't create playlist of name '%s'" % base)
Пример #36
0
    def test_main(self):
        if os.name == "nt":
            path = u'C:\\foobar\\ä%s\\%s' % ("x" * 300, "x" * 300)
            path = limit_path(path)
            self.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255)
        else:
            path = '/foobar/ä%s/%s' % ("x" * 300, "x" * 300)
            path = limit_path(path)
            self.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255)

        path = fsnative(u"foo%s.ext" % (u"x" * 300))
        new = limit_path(path, ellipsis=False)
        self.assertTrue(is_fsnative(new))
        self.assertEqual(len(new), 255)
        self.assertTrue(new.endswith(fsnative(u"xx.ext")))

        new = limit_path(path)
        self.assertTrue(is_fsnative(new))
        self.assertEqual(len(new), 255)
        self.assertTrue(new.endswith(fsnative(u"...ext")))

        self.assertTrue(is_fsnative(limit_path(fsnative())))
        self.assertEqual(limit_path(fsnative()), fsnative())
Пример #37
0
    def test_main(self):
        if os.name == "nt":
            path = u'C:\\foobar\\ä%s\\%s' % ("x" * 300, "x" * 300)
            path = limit_path(path)
            self.failUnlessEqual(len(path), 3 + 6 + 1 + 255 + 1 + 255)
        else:
            path = '/foobar/ä%s/%s' % ("x" * 300, "x" * 300)
            path = limit_path(path)
            self.failUnlessEqual(len(path), 1 + 6 + 1 + 255 + 1 + 255)

        path = fsnative(u"foo%s.ext" % (u"x" * 300))
        new = limit_path(path, ellipsis=False)
        self.assertTrue(is_fsnative(new))
        self.assertEqual(len(new), 255)
        self.assertTrue(new.endswith(fsnative(u"xx.ext")))

        new = limit_path(path)
        self.assertTrue(is_fsnative(new))
        self.assertEqual(len(new), 255)
        self.assertTrue(new.endswith(fsnative(u"...ext")))

        self.assertTrue(is_fsnative(limit_path(fsnative())))
        self.assertEqual(limit_path(fsnative()), fsnative())
Пример #38
0
    def fromsongs(cls, dir_, songs, library=None):
        assert is_fsnative(dir_)

        if len(songs) == 1:
            title = songs[0].comma("title")
        else:
            title = ngettext(
                "%(title)s and %(count)d more", "%(title)s and %(count)d more",
                len(songs) - 1) % ({
                    'title': songs[0].comma("title"),
                    'count': len(songs) - 1
                })

        playlist = cls.new(dir_, title, library)
        playlist.extend(songs)
        return playlist
Пример #39
0
    def set_file(self, fileobj):
        if fileobj is None:
            path = None
        else:
            path = fileobj.name
            assert is_fsnative(path)

        # XXX: Don't reload if the file path is the same.
        # Could prevent updates if fileobj.name isn't defined
        if self._path == path:
            return

        self._file = fileobj
        self._path = path
        self._dirty = True
        self.queue_resize()
Пример #40
0
    def fromsongs(cls, dir_, songs, library=None):
        assert is_fsnative(dir_)

        if len(songs) == 1:
            title = songs[0].comma("title")
        else:
            title = ngettext(
                "%(title)s and %(count)d more",
                "%(title)s and %(count)d more",
                len(songs) - 1) % (
                    {'title': songs[0].comma("title"),
                     'count': len(songs) - 1})

        playlist = cls.new(dir_, title, library)
        playlist.extend(songs)
        return playlist
Пример #41
0
    def set_file(self, fileobj):
        if fileobj is None:
            path = None
        else:
            path = fileobj.name
            assert is_fsnative(path)

        # XXX: Don't reload if the file path is the same.
        # Could prevent updates if fileobj.name isn't defined
        if self._path == path:
            return

        self._file = fileobj
        self._path = path
        self._dirty = True
        self.queue_resize()
Пример #42
0
    def go_to(self, path_to_go):
        assert is_fsnative(path_to_go)

        # FIXME: what about non-normalized paths?
        model = self.get_model()

        # Find the top level row which has the largest common
        # path with the path we want to go to
        roots = dict([(p, i) for (i, p) in model.iterrows(None)])
        head, tail = path_to_go, fsnative(u"")
        to_find = []
        while head and head not in roots:
            new_head, tail = os.path.split(head)
            # this can happen for invalid paths on Windows
            if head == new_head:
                break
            head = new_head
            to_find.append(tail)
        if head not in roots:
            return
        start_iter = roots[head]

        # expand until we find the right directory or the last valid one
        # and select/scroll to it
        def search(view, model, iter_, to_find):
            tree_path = model.get_path(iter_)

            # we are where we want, select and scroll
            if not to_find:
                view.set_cursor(tree_path)
                view.scroll_to_cell(tree_path)
                return

            # expand the row
            view.expand_row(tree_path, False)

            next_ = to_find.pop(-1)
            for sub_iter, path in model.iterrows(iter_):
                if os.path.basename(path) == next_:
                    search(view, model, sub_iter, to_find)
                    break
            else:
                # we haven't found the right sub folder, select the parent
                # and stop
                search(view, model, iter_, [])

        search(self, model, start_iter, to_find)
Пример #43
0
    def go_to(self, path_to_go):
        assert is_fsnative(path_to_go)

        # FIXME: what about non-normalized paths?
        model = self.get_model()

        # Find the top level row which has the largest common
        # path with the path we want to go to
        roots = dict([(p, i) for (i, p) in model.iterrows(None)])
        head, tail = path_to_go, fsnative(u"")
        to_find = []
        while head and head not in roots:
            new_head, tail = os.path.split(head)
            # this can happen for invalid paths on Windows
            if head == new_head:
                break
            head = new_head
            to_find.append(tail)
        if head not in roots:
            return
        start_iter = roots[head]

        # expand until we find the right directory or the last valid one
        # and select/scroll to it
        def search(view, model, iter_, to_find):
            tree_path = model.get_path(iter_)

            # we are where we want, select and scroll
            if not to_find:
                view.set_cursor(tree_path)
                view.scroll_to_cell(tree_path)
                return

            # expand the row
            view.expand_row(tree_path, False)

            next_ = to_find.pop(-1)
            for sub_iter, path in model.iterrows(iter_):
                if os.path.basename(path) == next_:
                    search(view, model, sub_iter, to_find)
                    break
            else:
                # we haven't found the right sub folder, select the parent
                # and stop
                search(view, model, iter_, [])

        search(self, model, start_iter, to_find)
Пример #44
0
    def new(cls, dir_, base=_("New Playlist"), library=None):
        assert is_fsnative(dir_)

        if not (dir_ and os.path.realpath(dir_)):
            raise ValueError("Invalid playlist directory %r" % (dir_,))

        p = Playlist(dir_, "", library)
        i = 0
        try:
            p.rename(base)
        except ValueError:
            while not p.name:
                i += 1
                try:
                    p.rename("%s %d" % (base, i))
                except ValueError:
                    pass
        return p
Пример #45
0
    def new(cls, dir_, base=_("New Playlist"), library=None):
        assert is_fsnative(dir_)

        if not (dir_ and os.path.realpath(dir_)):
            raise ValueError("Invalid playlist directory %r" % (dir_, ))

        p = Playlist(dir_, "", library)
        i = 0
        try:
            p.rename(base)
        except ValueError:
            while not p.name:
                i += 1
                try:
                    p.rename("%s %d" % (base, i))
                except ValueError:
                    pass
        return p
Пример #46
0
    def match_path(self, path):
        assert is_fsnative(path)

        tail = os.path.splitdrive(path)[-1]

        # only match on the last n pieces of a filename, dictated by pattern
        # this means no pattern may effectively cross a /, despite .* doing so
        sep = os.path.sep
        matchon = sep + sep.join(tail.split(sep)[-self.slashes:])
        # work on unicode
        matchon = fsdecode(matchon, note=False)
        match = self.pattern.search(matchon)

        # dicts for all!
        if match is None:
            return {}
        else:
            return match.groupdict()
Пример #47
0
    def __setitem__(self, key, value):
        if not self.__dict__:
            # unpickle case.. we can't fail
            dict.__setitem__(self, key, value)
            return

        if key.startswith("~#"):
            assert isinstance(value, number_types)
        elif key in FILESYSTEM_TAGS:
            assert is_fsnative(value)
        else:
            value = text_type(value)

        dict.__setitem__(self, key, value)

        pop = self.__dict__.pop
        pop("album_key", None)
        pop("sort_key", None)
Пример #48
0
    def __setitem__(self, key, value):
        if not self.__dict__:
            # unpickle case.. we can't fail
            dict.__setitem__(self, key, value)
            return

        if key.startswith("~#"):
            assert isinstance(value, number_types)
        elif key in FILESYSTEM_TAGS:
            assert is_fsnative(value)
        else:
            value = text_type(value)

        dict.__setitem__(self, key, value)

        pop = self.__dict__.pop
        pop("album_key", None)
        pop("sort_key", None)
Пример #49
0
    def match_path(self, path):
        assert is_fsnative(path)

        tail = os.path.splitdrive(path)[-1]

        # only match on the last n pieces of a filename, dictated by pattern
        # this means no pattern may effectively cross a /, despite .* doing so
        sep = os.path.sep
        matchon = sep + sep.join(tail.split(sep)[-self.slashes:])
        # work on unicode
        matchon = fsdecode(matchon, note=False)
        match = self.pattern.search(matchon)

        # dicts for all!
        if match is None:
            return {}
        else:
            return match.groupdict()
Пример #50
0
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert is_fsnative(filename)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, ".tmp", "wb") as fileobj:
                self._config.write(fileobj)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
Пример #51
0
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert is_fsnative(filename)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, ".tmp", "wb") as fileobj:
                self._config.write(fileobj)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
Пример #52
0
def atomic_save(filename, suffix, mode):
    """Try to replace the content of a file in the safest way possible.

    * filename+suffix will be created during the process.
    * On UNIX this operation is atomic, on Windows it is not.

    with atomic_save("config.cfg", ".tmp", "wb") as f:
        f.write(data)

    Can raise.
    """

    assert is_fsnative(filename)

    temp_filename = filename + suffix
    fileobj = open(temp_filename, "wb")
    try:
        if fcntl is not None:
            fcntl.flock(fileobj.fileno(), fcntl.LOCK_EX)

        yield fileobj

        fileobj.flush()
        os.fsync(fileobj.fileno())

        # No atomic rename on windows
        if os.name == "nt":
            fileobj.close()
            try:
                os.remove(filename)
            except EnvironmentError:
                pass

        os.rename(temp_filename, filename)
    finally:
        if fcntl is not None:
            fcntl.flock(fileobj.fileno(), fcntl.LOCK_UN)
        fileobj.close()
Пример #53
0
def atomic_save(filename, suffix, mode):
    """Try to replace the content of a file in the safest way possible.

    * filename+suffix will be created during the process.
    * On UNIX this operation is atomic, on Windows it is not.

    with atomic_save("config.cfg", ".tmp", "wb") as f:
        f.write(data)

    Can raise.
    """

    assert is_fsnative(filename)

    temp_filename = filename + suffix
    fileobj = open(temp_filename, "wb")
    try:
        if fcntl is not None:
            fcntl.flock(fileobj.fileno(), fcntl.LOCK_EX)

        yield fileobj

        fileobj.flush()
        os.fsync(fileobj.fileno())

        # No atomic rename on windows
        if os.name == "nt":
            fileobj.close()
            try:
                os.remove(filename)
            except EnvironmentError:
                pass

        os.rename(temp_filename, filename)
    finally:
        if fcntl is not None:
            fcntl.flock(fileobj.fileno(), fcntl.LOCK_UN)
        fileobj.close()
Пример #54
0
    def __init__(self, initial=None, filter=filesel_filter, folders=None):
        """
        initial -- a path to a file which should be shown initially
        filter -- a function which filters paths shown in the file list
        folders -- list of shown folders in the directory tree
        """

        super(FileSelector, self).__init__(
            orientation=Gtk.Orientation.VERTICAL)
        self.__filter = filter

        if initial is not None:
            assert is_fsnative(initial)

        if initial and os.path.isfile(initial):
            initial = os.path.dirname(initial)
        dirlist = DirectoryTree(initial, folders=folders)

        model = ObjectStore()
        filelist = AllTreeView(model=model)

        column = TreeViewColumn(title=_("Songs"))
        column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        render = Gtk.CellRendererPixbuf()
        render.props.xpad = 3

        def cell_icon(column, cell, model, iter_, userdata):
            value = model.get_value(iter_)
            if is_image(value):
                cell.set_property('icon-name', Icons.IMAGE_X_GENERIC)
            else:
                cell.set_property('icon-name', Icons.AUDIO_X_GENERIC)

        column.set_cell_data_func(render, cell_icon)

        column.pack_start(render, False)
        render = Gtk.CellRendererText()
        if filelist.supports_hints():
            render.set_property('ellipsize', Pango.EllipsizeMode.END)
        column.pack_start(render, True)

        def cell_data(column, cell, model, iter_, userdata):
            value = model.get_value(iter_)
            cell.set_property('text', fsdecode(os.path.basename(value)))

        column.set_cell_data_func(render, cell_data)

        filelist.append_column(column)
        filelist.set_rules_hint(True)
        filelist.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
        filelist.set_search_equal_func(search_func, False)
        filelist.set_search_column(0)

        self.__sig = filelist.get_selection().connect(
            'changed', self.__changed)

        dirlist.get_selection().connect(
            'changed', self.__dir_selection_changed, filelist)
        dirlist.get_selection().emit('changed')

        def select_all_files(view, path, col, fileselection):
            view.expand_row(path, False)
            fileselection.select_all()
        dirlist.connect('row-activated', select_all_files,
            filelist.get_selection())

        sw = ScrolledWindow()
        sw.add(dirlist)
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        sw.set_shadow_type(Gtk.ShadowType.IN)
        self.pack1(sw, resize=True)

        sw = ScrolledWindow()
        sw.add(filelist)
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        sw.set_shadow_type(Gtk.ShadowType.IN)
        self.pack2(sw, resize=True)
Пример #55
0
    def __init__(self, initial=None, folders=None):
        """
        initial -- the path to select/scroll to
        folders -- a list of paths to show in the tree view, None
                   will result in a separator.
        """

        model = ObjectTreeStore()
        super(DirectoryTree, self).__init__(model=model)

        if initial is not None:
            assert is_fsnative(initial)

        column = TreeViewColumn(title=_("Folders"))
        column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        render = Gtk.CellRendererPixbuf()
        render.set_property('icon-name', Icons.FOLDER)
        render.props.xpad = 3
        column.pack_start(render, False)
        render = Gtk.CellRendererText()
        if self.supports_hints():
            render.set_property('ellipsize', Pango.EllipsizeMode.END)
        column.pack_start(render, True)

        def cell_data(column, cell, model, iter_, userdata):
            value = model.get_value(iter_)
            if value is not None:
                text = fsdecode(os.path.basename(value) or value)
                cell.set_property('text', text)

        column.set_cell_data_func(render, cell_data)

        self.append_column(column)
        self.set_search_equal_func(search_func, True)
        self.set_search_column(0)

        if folders is None:
            folders = []

        for path in folders:
            niter = model.append(None, [path])
            if path is not None:
                assert is_fsnative(path)
                model.append(niter, ["dummy"])

        self.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
        self.connect(
            'test-expand-row', DirectoryTree.__expanded, model)

        self.set_row_separator_func(
            lambda model, iter_, data: model.get_value(iter_) is None, None)

        if initial:
            self.go_to(initial)

        menu = Gtk.Menu()
        m = qltk.MenuItem(_(u"_New Folder…"), Icons.DOCUMENT_NEW)
        m.connect('activate', self.__mkdir)
        menu.append(m)
        m = qltk.MenuItem(_("_Delete"), Icons.EDIT_DELETE)
        m.connect('activate', self.__rmdir)
        menu.append(m)
        m = qltk.MenuItem(_("_Refresh"), Icons.VIEW_REFRESH)
        m.connect('activate', self.__refresh)
        menu.append(m)
        m = qltk.MenuItem(_("_Select All Subfolders"), Icons.FOLDER)
        m.connect('activate', self.__expand)
        menu.append(m)
        menu.show_all()
        connect_obj(self, 'popup-menu', self.__popup_menu, menu)

        # Allow to drag and drop files from outside
        targets = [
            ("text/uri-list", 0, 42)
        ]
        targets = [Gtk.TargetEntry.new(*t) for t in targets]
        self.drag_dest_set(Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY)
        self.connect('drag-data-received', self.__drag_data_received)
Пример #56
0
import os
from gi.repository import Gtk
from quodlibet import formats, qltk
from quodlibet.qltk.wlw import WaitLoadWindow
from quodlibet.qltk.getstring import GetStringDialog
from quodlibet.util import escape
from quodlibet.util.collection import Playlist
from quodlibet.util.path import mkdir, fsdecode, is_fsnative
from quodlibet import const

# Directory for playlist files
from quodlibet.util.uri import URI

PLAYLISTS = os.path.join(const.USERDIR, "playlists")
assert is_fsnative(PLAYLISTS)
if not os.path.isdir(PLAYLISTS):
    mkdir(PLAYLISTS)


class ConfirmRemovePlaylistDialog(qltk.Message):
    def __init__(self, parent, playlist):
        title = (_("Are you sure you want to delete the playlist '%s'?") %
                 escape(playlist.name))
        description = (_("All information about the selected playlist "
                         "will be deleted and can not be restored."))

        super(ConfirmRemovePlaylistDialog,
              self).__init__(Gtk.MessageType.WARNING, parent, title,
                             description, Gtk.ButtonsType.NONE)