def run(self, dist):
        platform = get_platform()
        cwd = Path.cwd()

        if platform == 'Windows':
            bl_exe = "Blender Launcher.exe"
            blu_exe = "Blender Launcher Updater.exe"
        elif platform == 'Linux':
            bl_exe = "Blender Launcher"
            blu_exe = "Blender Launcher Updater"

        source = cwd / bl_exe
        dist = cwd / blu_exe

        with open(source.as_posix(), 'rb') as f1, open(dist.as_posix(),
                                                       'wb') as f2:
            copyfileobj(f1, f2)

        if platform == 'Windows':
            _popen([dist.as_posix(), "-update"])
        elif platform == 'Linux':
            os.chmod(dist.as_posix(), 0o744)
            _popen('nohup "' + dist.as_posix() + '" -update')

        self.parent.destroy()
예제 #2
0
def handle_exception(exc_type, exc_value, exc_traceback):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return

    _format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    logging.basicConfig(filename="Blender Launcher.log", format=_format)
    logger.error(get_platform(), exc_info=(exc_type, exc_value, exc_traceback))
    def download(self):
        self.link = "https://github.com/DotBow/Blender-Launcher/releases/download/{0}/Blender_Launcher_{0}_{1}_x64.zip".format(
            self.tag, get_platform())
        self.downlaoder = Downloader(self.parent.manager, self.link)
        self.downlaoder.progress_changed.connect(self.set_progress_bar)
        self.downlaoder.finished.connect(self.extract)
        self.downlaoder.start()

        self.show()
    def show_folder(self):
        platform = get_platform()
        library_folder = Path(get_library_folder())
        folder = library_folder / self.link

        if platform == 'Windows':
            os.startfile(folder.as_posix())
        elif platform == 'Linux':
            subprocess.call(["xdg-open", folder.as_posix()])
예제 #5
0
    def run(self):
        library_folder = Path(get_library_folder())

        if get_platform() == 'Windows':
            blender_exe = "blender.exe"
        elif get_platform() == 'Linux':
            blender_exe = "blender"

        for dir in library_folder.iterdir():
            if dir.is_dir():
                for build in dir.iterdir():
                    path = library_folder / dir / build / blender_exe

                    if path.is_file():
                        self.build_found.emit(dir / build)

        self.finished.emit()
        return
예제 #6
0
    def get_name(self):
        if self.link_type == 'link':
            platform = get_platform()

            if platform == 'Linux':
                return Path(self.link).with_suffix('').stem
            elif platform == 'Windows':
                return Path(self.link).stem
        elif self.link_type == 'path':
            return Path(self.link).name
예제 #7
0
    def _show(self):
        platform = get_platform()

        if platform == "Windows":
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.show()
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.show()
        elif platform == "Linux":
            self.show()
            self.activateWindow()

        self.set_status()
        self.show_signal.emit()
예제 #8
0
def create_shortcut(folder, name):
    platform = get_platform()
    library_folder = Path(get_library_folder())

    if platform == 'Windows':
        targetpath = library_folder / folder / "blender.exe"
        workingdir = library_folder / folder
        desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, None, 0)
        dist = Path(desktop) / (name + ".lnk")

        if getattr(sys, 'frozen', False):
            icon = sys._MEIPASS + "/files/winblender.ico"
        else:
            icon = Path(
                "./resources/icons/winblender.ico").resolve().as_posix()

        icon_location = library_folder / folder / "winblender.ico"
        copyfile(icon, icon_location.as_posix())

        _WSHELL = win32com.client.Dispatch("Wscript.Shell")
        wscript = _WSHELL.CreateShortCut(dist.as_posix())
        wscript.Targetpath = targetpath.as_posix()
        wscript.WorkingDirectory = workingdir.as_posix()
        wscript.WindowStyle = 0
        wscript.IconLocation = icon_location.as_posix()
        wscript.save()
    elif platform == 'Linux':
        _exec = library_folder / folder / "blender"
        icon = library_folder / folder / "blender.svg"
        desktop = Path.home() / "Desktop"
        filename = name.replace(' ', '-')
        dist = desktop / (filename + ".desktop")

        desktop_entry = \
            "[Desktop Entry]\n" + \
            "Name={0}\n".format(name) + \
            "Comment=3D modeling, animation, rendering and post-production\n" + \
            "Keywords=3d;cg;modeling;animation;painting;sculpting;texturing;video editing;video tracking;rendering;render engine;cycles;game engine;python;\n" + \
            "Icon={0}\n".format(icon.as_posix().replace(' ', r'\ ')) + \
            "Terminal=false\n" + \
            "Type=Application\n" + \
            "Categories=Graphics;3DGraphics;\n" + \
            "MimeType=application/x-blender;\n" + \
            "Exec={0} %f".format(_exec.as_posix().replace(' ', r'\ '))

        with open(dist, 'w') as file:
            file.write(desktop_entry)

        os.chmod(dist, 0o744)
예제 #9
0
def set_launch_when_system_starts(is_checked):
    if get_platform() == 'Windows':
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
                             0, winreg.KEY_SET_VALUE)

        if (is_checked):
            path = sys.executable
            winreg.SetValueEx(key, 'Blender Launcher', 0, winreg.REG_SZ, path)
        else:
            try:
                winreg.DeleteValue(key, 'Blender Launcher')
            except Exception:
                pass

        key.Close()
예제 #10
0
    def run(self):
        platform = get_platform()

        if platform == 'Windows':
            b3d_exe = Path(self.path) / "blender.exe"
            subprocess.call([str(b3d_exe), "-r"],
                            creationflags=CREATE_NO_WINDOW,
                            shell=True,
                            stdout=PIPE,
                            stderr=STDOUT,
                            stdin=DEVNULL)
        elif platform == 'Linux':
            b3d_exe = Path(self.path) / "blender"
            pass

        self.finished.emit(0)
        return
    def create_symlink(self):
        target = self.link.as_posix()
        link = (Path(get_library_folder()) / "bl_symlink").as_posix()
        platform = get_platform()

        if platform == 'Windows':
            if os.path.exists(link):
                if os.path.isdir(link):
                    os.rmdir(link)

            _check_call('mklink /J "{0}" "{1}"'.format(link, target))
        elif platform == 'Linux':
            if os.path.exists(link):
                if os.path.islink(link):
                    os.unlink(link)

            os.symlink(target, link)
예제 #12
0
    def scrap_download_links(self, url, branch_type, _limit=None):
        platform = get_platform()
        r = self.manager.request('GET', url)
        content = r.data
        soup = BeautifulSoup(content, 'html.parser')
        links = []

        if platform == 'Windows':
            for tag in soup.find_all(
                    limit=_limit, href=re.compile(r'blender-.+win.+64.+zip')):
                links.append(self.new_blender_build(tag, url, branch_type))
        elif platform == 'Linux':
            for tag in soup.find_all(
                    limit=_limit, href=re.compile(r'blender-.+lin.+64.+tar')):
                links.append(self.new_blender_build(tag, url, branch_type))

        r.release_conn()
        r.close()
        return links
예제 #13
0
    def create_symlink(self):
        target = self.link.as_posix()
        link = (Path(get_library_folder()) / "bl_symlink").as_posix()
        platform = get_platform()

        if platform == 'Windows':
            if os.path.exists(link):
                if os.path.isdir(link):
                    os.rmdir(link)

            check_call('mklink /J "{0}" "{1}"'.format(link, target),
                       creationflags=CREATE_NO_WINDOW,
                       shell=True,
                       stderr=DEVNULL,
                       stdin=DEVNULL)
        elif platform == 'Linux':
            if os.path.exists(link):
                if os.path.islink(link):
                    os.unlink(link)

            os.symlink(target, link)
예제 #14
0
    def launch(self):
        self.item.setSelected(True)

        if hasattr(self, "NewItemLabel"):
            self.NewItemLabel.hide()

        platform = get_platform()
        library_folder = Path(get_library_folder())
        blender_args = get_blender_startup_arguments()

        if platform == 'Windows':
            b3d_exe = library_folder / self.link / "blender.exe"

            if blender_args == "":
                proc = _popen(b3d_exe.as_posix())
            else:
                args = [b3d_exe.as_posix()]
                args.extend(blender_args.split(' '))
                proc = _popen(args)
        elif platform == 'Linux':
            bash_args = get_bash_arguments()

            if bash_args != '':
                bash_args = bash_args + " nohup"
            else:
                bash_args = "nohup"

            b3d_exe = library_folder / self.link / "blender"
            proc = _popen('{0} "{1}" {2}'.format(
                bash_args, b3d_exe.as_posix(), blender_args))

        if self.observer is None:
            self.observer = Observer(self)
            self.observer.count_changed.connect(self.proc_count_changed)
            self.observer.started.connect(self.observer_started)
            self.observer.finished.connect(self.observer_finished)
            self.observer.start()

        self.observer.append_proc(proc)
예제 #15
0
def main():
    if "-update" in sys.argv:
        platform = get_platform()
        temp = Path(tempfile.gettempdir())
        cwd = Path.cwd()

        if platform == 'Windows':
            bl_exe = "Blender Launcher.exe"
        elif platform == 'Linux':
            bl_exe = "Blender Launcher"

        source = (temp / bl_exe).as_posix()
        dist = (cwd / bl_exe).as_posix()

        with open(source, 'rb') as f1, open(dist, 'wb') as f2:
            copyfileobj(f1, f2)

        if platform == 'Windows':
            _popen([dist])
        elif platform == 'Linux':
            os.chmod(dist, 0o744)
            _popen('nohup "' + dist + '"')

        sys.exit(0)

    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    app.setApplicationVersion(version)
    app.setQuitOnLastWindowClosed(False)

    socket = QLocalSocket()
    socket.connectToServer("blender-launcher-server")
    is_running = socket.waitForConnected()

    if not is_running:
        socket.close()
        BlenderLauncher(app)
        app.exec_()
예제 #16
0
def get_launch_when_system_starts():
    if get_platform() == 'Windows':
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run')
        path = sys.executable
        _, count, _ = winreg.QueryInfoKey(key)

        for i in range(count):
            try:
                name, value, _ = winreg.EnumValue(key, i)

                if name == 'Blender Launcher':
                    if value == path:
                        return True
                    else:
                        return False
            except WindowsError:
                pass

        key.Close()
        return False
    else:
        return False
    def launch(self):
        self.item.setSelected(True)

        if hasattr(self, "NewItemLabel"):
            self.NewItemLabel.hide()

        platform = get_platform()
        library_folder = Path(get_library_folder())

        if platform == 'Windows':
            b3d_exe = library_folder / self.link / "blender.exe"
            proc = _popen(b3d_exe.as_posix())
        elif platform == 'Linux':
            b3d_exe = library_folder / self.link / "blender"
            proc = _popen('nohup "' + b3d_exe.as_posix() + '"')

        if self.observer is None:
            self.observer = Observer(self)
            self.observer.count_changed.connect(self.proc_count_changed)
            self.observer.started.connect(self.observer_started)
            self.observer.finished.connect(self.observer_finished)
            self.observer.start()

        self.observer.append_proc(proc)
예제 #18
0
    def write_build_info(self):
        # Read Blender Version
        platform = get_platform()

        if platform == 'Windows':
            blender_exe = "blender.exe"
        elif platform == 'Linux':
            blender_exe = "blender"

        exe_path = self.path / blender_exe

        try:
            if platform == 'Windows':
                info = subprocess.check_output([exe_path.as_posix(), "-v"],
                                               creationflags=CREATE_NO_WINDOW,
                                               shell=True,
                                               stderr=DEVNULL,
                                               stdin=DEVNULL)
            elif platform == 'Linux':
                info = subprocess.check_output([exe_path.as_posix(), "-v"],
                                               shell=False,
                                               stderr=DEVNULL,
                                               stdin=DEVNULL)
        except CalledProcessError:
            return 1

        info = info.decode('UTF-8')

        set_locale()
        ctime = re.search("build commit time: " + "(.*)", info)[1].rstrip()
        cdate = re.search("build commit date: " + "(.*)", info)[1].rstrip()
        strptime = time.strptime(cdate + ' ' + ctime, "%Y-%m-%d %H:%M")
        commit_time = time.strftime("%d-%b-%y-%H:%M", strptime)
        build_hash = re.search("build hash: " + "(.*)", info)[1].rstrip()
        subversion = re.search("Blender " + "(.*)", info)[1].rstrip()

        try:
            subfolder = self.path.parent.name
            name = self.path.name

            if platform == 'Windows':
                folder_parts = name.replace("blender-",
                                            "").replace("-windows64",
                                                        "").rsplit('-', 2)
            elif platform == 'Linux':
                folder_parts = name.replace("blender-",
                                            "").replace("-linux64",
                                                        "").rsplit('-', 2)

            if subfolder == 'experimental':
                branch = folder_parts[0]
            elif subfolder == 'daily':
                branch = "daily"
            elif subfolder == 'stable':
                branch = "stable"
                subversion = folder_parts[0]
            elif subfolder == 'custom':
                branch = self.path.name
        except Exception:
            branch = None

        # Write Version Information
        data = {}
        data['file_version'] = BuildInfo.file_version
        data['blinfo'] = []
        data['blinfo'].append({
            'branch': branch,
            'subversion': subversion,
            'build_hash': build_hash,
            'commit_time': commit_time,
        })

        path = self.path / '.blinfo'

        with open(path, 'w') as file:
            json.dump(data, file)

        return 0
예제 #19
0
    def run(self):
        self.started.emit()

        blender_zip = self.manager.request('GET',
                                           self.build_info.link,
                                           preload_content=False)
        size = blender_zip.headers['Content-Length']

        library_folder = Path(get_library_folder())
        temp_folder = library_folder / ".temp"

        # Create temp directory
        if not temp_folder.is_dir():
            temp_folder.mkdir()

        temp_folder = temp_folder / Path(self.build_info.link).name

        # Download
        with open(temp_folder, 'wb') as file:
            for chunk in blender_zip.stream(16 * 1024):
                file.write(chunk)
                progress = os.stat(temp_folder).st_size / int(size)
                self.progress_changed.emit(progress, "Downloading: %p%")

        blender_zip.release_conn()
        blender_zip.close()

        self.platform = get_platform()

        if self.build_info.branch == 'stable':
            dist = library_folder / 'stable'
        elif self.build_info.branch == 'daily':
            dist = library_folder / 'daily'
        else:
            dist = library_folder / 'experimental'

        # Extract
        self.progress_changed.emit(0, "Extracting: %p%")

        if self.platform == 'Windows':
            zf = zipfile.ZipFile(temp_folder)
            version = zf.infolist()[0].filename.split('/')[0]
            uncompress_size = sum((file.file_size for file in zf.infolist()))
            extracted_size = 0

            for file in zf.infolist():
                zf.extract(file, dist)
                extracted_size += file.file_size
                progress = extracted_size / uncompress_size
                self.progress_changed.emit(progress, "Extracting: %p%")

            zf.close()
            path = Path(self.build_info.link).stem
        elif self.platform == 'Linux':
            tar = tarfile.open(temp_folder)
            version = tar.getnames()[0].split('/')[0]
            uncompress_size = sum((member.size for member in tar.getmembers()))
            extracted_size = 0

            for member in tar.getmembers():
                tar.extract(member, path=dist)
                extracted_size += member.size
                progress = extracted_size / uncompress_size
                self.progress_changed.emit(progress, "Extracting: %p%")

            tar.close()
            path = Path(self.build_info.link).stem.replace('.tar', '')

        self.finished.emit(dist / path)
        return
    def draw(self, build_info):
        if build_info is None:
            self.infoLabel.setText(
                ("Build *{0}* is damaged!").format(Path(self.link).name))
            self.launchButton.setText("Delete")
            self.launchButton.clicked.connect(self.ask_remove_from_drive)
            self.setEnabled(True)
            return

        for i in reversed(range(self.layout.count())):
            self.layout.itemAt(i).widget().setParent(None)

        self.build_info = build_info
        self.branch = self.build_info.branch
        self.item.date = build_info.commit_time

        self.icon_favorite = QIcon(":resources/icons/favorite.svg")
        self.icon_fake = QIcon(":resources/icons/fake.svg")
        self.icon_delete = QIcon(":resources/icons/delete.svg")

        self.launchButton = QPushButton("Launch")
        self.launchButton.setMinimumWidth(75)
        self.launchButton.setProperty("LaunchButton", True)

        self.subversionLabel = QLabel()
        self.branchLabel = QLabel()
        self.commitTimeLabel = QLabel()
        self.buildHashLabel = QLabel()

        self.countButton = QPushButton("0")
        self.countButton.setEnabled(False)
        self.countButton.setProperty("Count", True)
        self.countButton.hide()
        self.countButton.setFixedSize(24, 24)

        self.widgetFavorite = QPushButton()
        self.widgetFavorite.setEnabled(False)
        self.widgetFavorite.setFixedSize(24, 24)
        self.widgetFavorite.setIcon(self.icon_fake)
        self.widgetFavorite.setProperty("Icon", True)

        self.layout.addWidget(self.launchButton)
        self.layout.addWidget(self.subversionLabel)
        self.layout.addWidget(self.branchLabel)
        self.layout.addWidget(self.commitTimeLabel)
        self.layout.addWidget(self.buildHashLabel)
        self.layout.addStretch()
        self.layout.addWidget(self.countButton)
        self.layout.addWidget(self.widgetFavorite)

        self.launchButton.clicked.connect(self.launch)
        self.subversionLabel.setText(self.build_info.subversion)

        if self.branch == 'lts':
            branch_name = "LTS"
        else:
            branch_name = self.branch.replace('-', ' ').title()

        self.branchLabel.setText(branch_name)

        self.commitTimeLabel.setText(self.build_info.commit_time)
        self.buildHashLabel.setText(self.build_info.build_hash)

        # Context menu
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.context_menu)

        self.menu = QMenu()
        self.menu.setFont(self.parent.font)

        self.menu_extended = QMenu()
        self.menu_extended.setFont(self.parent.font)

        self.deleteAction = QAction("Delete From Drive", self)
        self.deleteAction.setIcon(self.icon_delete)
        self.deleteAction.triggered.connect(self.ask_remove_from_drive)

        self.setAsFavoriteAction = QAction("Mark As Favorite", self)
        self.setAsFavoriteAction.setIcon(self.icon_favorite)
        self.setAsFavoriteAction.triggered.connect(self.set_favorite)

        self.registerExtentionAction = QAction("Register Extension")
        self.registerExtentionAction.triggered.connect(self.register_extension)

        self.createShortcutAction = QAction("Create Shortcut")
        self.createShortcutAction.triggered.connect(self.create_shortcut)

        self.showFolderAction = QAction("Show Folder")
        self.showFolderAction.triggered.connect(self.show_folder)

        self.createSymlinkAction = QAction("Create Symlink")
        self.createSymlinkAction.triggered.connect(self.create_symlink)

        self.menu.addAction(self.setAsFavoriteAction)

        if get_platform() == 'Windows':
            self.menu.addAction(self.registerExtentionAction)

        self.menu.addAction(self.createShortcutAction)
        self.menu.addAction(self.createSymlinkAction)
        self.menu.addAction(self.showFolderAction)
        self.menu.addAction(self.deleteAction)

        self.menu_extended.addAction(self.deleteAction)

        if self.show_new:
            self.NewItemLabel = QLabel("New")
            self.NewItemLabel.setAlignment(Qt.AlignRight | Qt.AlignCenter)
            self.NewItemLabel.setIndent(6)
            self.layout.addWidget(self.NewItemLabel)

            if get_mark_as_favorite() == 0:
                pass
            elif (get_mark_as_favorite() == 1 and self.branch == "stable"):
                self.set_favorite()
            elif (get_mark_as_favorite() == 2 and self.branch == "daily"):
                self.set_favorite()
            elif get_mark_as_favorite() == 3:
                self.set_favorite()
        elif get_favorite_path() == self.link:
            self.set_favorite()

        self.setEnabled(True)
        self.list_widget.sortItems()
        self.list_widget.resize_labels(
            ('subversionLabel', 'branchLabel',
             'commitTimeLabel', 'buildHashLabel'))
from modules._platform import _check_call, _popen, get_platform
from modules.build_info import BuildInfoReader
from modules.settings import (get_favorite_path, get_library_folder,
                              get_mark_as_favorite, set_favorite_path)
from modules.shortcut import create_shortcut
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QCursor, QIcon
from PyQt5.QtWidgets import (QAction, QApplication, QHBoxLayout, QLabel, QMenu,
                             QPushButton, QWidget)
from threads.observer import Observer
from threads.register import Register
from threads.remover import Remover
from windows.dialog_window import DialogIcon, DialogWindow

if get_platform() == 'Windows':
    from subprocess import CREATE_NO_WINDOW


class LibraryWidget(QWidget):
    def __init__(self, parent, item, link, list_widget, show_new=False):
        super(LibraryWidget, self).__init__(None)

        self.parent = parent
        self.item = item
        self.link = link
        self.list_widget = list_widget
        self.show_new = show_new
        self.observer = None
        self.build_info = None