コード例 #1
0
    def read_build_info(self, folder):
        path = Path(get_library_folder()) / folder / '.blinfo'

        if not path.is_file():
            if self.write_build_info(folder) == 1:
                return None

        with open(path) as file:
            data = json.load(file)

        if ('file_version' not in data) or (data['file_version'] !=
                                            BuildInfo.file_version):
            if self.write_build_info(folder) == 1:
                return None
            else:
                return self.read_build_info(folder)
        else:
            blinfo = data['blinfo'][0]
            link = Path(get_library_folder()) / folder

            build_info = BuildInfo('path', link, blinfo['subversion'],
                                   blinfo['build_hash'], blinfo['commit_time'],
                                   blinfo['branch'])

            return build_info
コード例 #2
0
 def remove_from_drive(self):
     self.launchButton.setText("Deleting")
     self.setEnabled(False)
     path = Path(get_library_folder()) / self.link
     self.remover = Remover(path)
     self.remover.finished.connect(self.remover_finished)
     self.remover.start()
コード例 #3
0
    def run(self):
        self.started.emit()

        request = self.manager.request('GET', self.link, preload_content=False)
        temp_folder = Path(get_library_folder()) / ".temp"

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

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

        # Download
        with open(dist, 'wb') as file:
            size = int(request.headers['Content-Length'])

            for chunk in request.stream(16 * 1024):
                file.write(chunk)
                progress = os.stat(dist).st_size / size
                self.progress_changed.emit(progress, "Downloading: %p%")

        request.release_conn()
        request.close()

        self.finished.emit(dist)
        return
コード例 #4
0
    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 set_library_folder(self):
        library_folder = str(get_library_folder())
        new_library_folder = QFileDialog.getExistingDirectory(
            self, "Select Library Folder", library_folder,
            options=QFileDialog.DontUseNativeDialog | QFileDialog.ShowDirsOnly)

        if new_library_folder and (library_folder != new_library_folder):
            self.LibraryFolderLineEdit.setText(new_library_folder)
            set_library_folder(new_library_folder)
            self.parent.draw_library(clear=True)
コード例 #6
0
    def __init__(self, app):
        super().__init__()
        self.setupUi(self)
        self.setAcceptDrops(True)

        # Server
        self.server = QLocalServer()
        self.server.listen("blender-launcher-server")
        self.server.newConnection.connect(self.new_connection)

        # Global scope
        self.app = app
        self.favorite = None
        self.status = "None"
        self.app_state = AppState.IDLE
        self.cashed_builds = []
        self.notification_pool = []
        self.windows = [self]
        self.manager = PoolManager(num_pools=50, maxsize=10)
        self.timer = None
        self.started = True
        self.latest_tag = ""
        self.new_downloads = False

        # Setup window
        self.setWindowTitle("Blender Launcher")
        self.app.setWindowIcon(
            QIcon(taskbar_icon_paths[get_taskbar_icon_color()]))

        # Setup font
        QFontDatabase.addApplicationFont(
            ":/resources/fonts/OpenSans-SemiBold.ttf")
        self.font = QFont("Open Sans SemiBold", 10)
        self.font.setHintingPreference(QFont.PreferNoHinting)
        self.app.setFont(self.font)

        # Setup style
        file = QFile(":/resources/styles/global.qss")
        file.open(QFile.ReadOnly | QFile.Text)
        self.style_sheet = QTextStream(file).readAll()
        self.app.setStyleSheet(self.style_sheet)

        # Check library folder
        if is_library_folder_valid() is False:
            self.dlg = DialogWindow(
                self,
                title="Information",
                text="First, choose where Blender<br>builds will be stored",
                accept_text="Continue",
                cancel_text=None,
                icon=DialogIcon.INFO)
            self.dlg.accepted.connect(self.set_library_folder)
        else:
            create_library_folders(get_library_folder())
            self.draw()
コード例 #7
0
    def init_extractor(self, source):
        library_folder = Path(get_library_folder())

        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'

        self.thread = Extractor(self.parent.manager, source, dist)
        self.thread.progress_changed.connect(self.set_progress_bar)
        self.thread.finished.connect(self.download_finished)
        self.thread.start()
コード例 #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 init_extractor(self, source):
        self.cancelButton.setEnabled(False)
        library_folder = Path(get_library_folder())

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

        self.extractor = Extractor(self.parent.manager, source, dist)
        self.extractor.progress_changed.connect(self.set_progress_bar)
        self.extractor.finished.connect(self.init_template_installer)
        self.extractor.start()
コード例 #10
0
    def context_menu(self):
        if len(self.list_widget.selectedItems()) > 1:
            self.menu_extended.exec_(QCursor.pos())
            return

        link_path = Path(get_library_folder()) / "bl_symlink"
        link = link_path.as_posix()

        if os.path.exists(link):
            if (os.path.isdir(link) or os.path.islink(link)):
                if link_path.resolve() == self.link:
                    self.createSymlinkAction.setEnabled(False)
                    self.menu.exec_(QCursor.pos())
                    return

        self.createSymlinkAction.setEnabled(True)
        self.menu.exec_(QCursor.pos())
コード例 #11
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))
        elif platform == 'Linux':
            if os.path.exists(link):
                if os.path.islink(link):
                    os.unlink(link)

            os.symlink(target, link)
コード例 #12
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
コード例 #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 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)
コード例 #16
0
    def __init__(self, parent):
        super().__init__()
        self.setWindowFlag(Qt.SubWindow)

        self.parent = parent
        self.setupUi(self)

        self.setWindowTitle("Settings")

        self.HeaderLayout = QHBoxLayout()
        self.HeaderLayout.setContentsMargins(36, 1, 1, 0)
        self.HeaderLayout.setSpacing(0)
        self.CentralLayout.addLayout(self.HeaderLayout)

        self.CloseButton = \
            QPushButton(QIcon(":resources/icons/close.svg"), "")
        self.CloseButton.setIconSize(QSize(20, 20))
        self.CloseButton.setFixedSize(36, 32)
        self.CloseButton.setProperty("HeaderButton", True)
        self.CloseButton.setProperty("CloseButton", True)
        self.CloseButton.clicked.connect(self.close)
        self.HeaderLabel = QLabel("Settings")
        self.HeaderLabel.setAlignment(Qt.AlignCenter)

        self.HeaderLayout.addWidget(self.HeaderLabel, 1)
        self.HeaderLayout.addWidget(self.CloseButton, 0, Qt.AlignRight)

        # Library Folder
        self.LibraryFolderLineEdit = QLineEdit()
        self.LibraryFolderLineEdit.setText(str(get_library_folder()))
        self.LibraryFolderLineEdit.setContextMenuPolicy(Qt.NoContextMenu)
        self.LibraryFolderLineEdit.setReadOnly(True)
        self.LibraryFolderLineEdit.setCursorPosition(0)

        self.SetLibraryFolderButton = \
            QPushButton(QIcon(":resources/icons/folder.svg"), "")
        self.SetLibraryFolderButton.clicked.connect(self.set_library_folder)
        self.ReloadLibraryFolderContentButton = QPushButton(
            "Reload Library Folder Content")
        self.ReloadLibraryFolderContentButton.clicked.connect(
            lambda: self.parent.draw_library(True))

        self.LibraryFolderLayout = QHBoxLayout()
        self.LibraryFolderLayout.setContentsMargins(0, 0, 0, 0)
        self.LibraryFolderLayout.setSpacing(0)

        self.LibraryFolderLayout.addWidget(self.LibraryFolderLineEdit)
        self.LibraryFolderLayout.addWidget(self.SetLibraryFolderButton)

        # Launch When System Starts
        self.LaunchWhenSystemStartsCheckBox = QCheckBox(
            "Launch When System Starts")
        self.LaunchWhenSystemStartsCheckBox.setChecked(
            get_launch_when_system_starts())
        self.LaunchWhenSystemStartsCheckBox.clicked.connect(
            self.toggle_launch_when_system_starts)

        # Launch Minimized To Tray
        self.LaunchMinimizedToTrayCheckBox = QCheckBox(
            "Launch Minimized To Tray")
        self.LaunchMinimizedToTrayCheckBox.setChecked(
            get_launch_minimized_to_tray())
        self.LaunchMinimizedToTrayCheckBox.clicked.connect(
            self.toggle_launch_minimized_to_tray)

        # High Dpi Scaling
        self.EnableHighDpiScalingCheckBox = \
            QCheckBox("Enable High DPI Scaling")
        self.EnableHighDpiScalingCheckBox.clicked.connect(
            self.toggle_enable_high_dpi_scaling)
        self.EnableHighDpiScalingCheckBox.setChecked(
            get_enable_high_dpi_scaling())

        # Taskbar Icon Color
        self.TaskbarIconColorComboBox = QComboBox()
        self.TaskbarIconColorComboBox.addItems(taskbar_icon_colors.keys())
        self.TaskbarIconColorComboBox.setCurrentIndex(
            get_taskbar_icon_color())
        self.TaskbarIconColorComboBox.activated[str].connect(
            self.change_taskbar_icon_color)

        # Default Library Page
        self.DefaultLibraryPageComboBox = QComboBox()
        self.DefaultLibraryPageComboBox.addItems(library_pages.keys())
        self.DefaultLibraryPageComboBox.setCurrentIndex(
            get_default_library_page())
        self.DefaultLibraryPageComboBox.activated[str].connect(
            self.change_default_library_page)

        # Default Downloads Page
        self.DefaultDownloadsPageComboBox = QComboBox()
        self.DefaultDownloadsPageComboBox.addItems(downloads_pages.keys())
        self.DefaultDownloadsPageComboBox.setCurrentIndex(
            get_default_downloads_page())
        self.DefaultDownloadsPageComboBox.activated[str].connect(
            self.change_default_downloads_page)

        # Notifications
        self.EnableNewBuildsNotifications = QCheckBox(
            "When New Builds Are Available")
        self.EnableNewBuildsNotifications.clicked.connect(
            self.toggle_enable_new_builds_notifications)
        self.EnableNewBuildsNotifications.setChecked(
            get_enable_new_builds_notifications())

        self.EnableDownloadNotifications = QCheckBox(
            "When Downloading Is Finished")
        self.EnableDownloadNotifications.clicked.connect(
            self.toggle_enable_download_notifications)
        self.EnableDownloadNotifications.setChecked(
            get_enable_download_notifications())

        # Mark As Favorite
        self.MarkAsFavorite = QComboBox()
        self.MarkAsFavorite.addItems(favorite_pages.keys())
        self.MarkAsFavorite.setCurrentIndex(
            get_mark_as_favorite())
        self.MarkAsFavorite.activated[str].connect(
            self.change_mark_as_favorite)

        # Layout
        self.SettingsLayout = QFormLayout()
        self.SettingsLayout.setContentsMargins(6, 6, 6, 6)
        self.SettingsLayout.setSpacing(6)
        self.SettingsLayout.setRowWrapPolicy(QFormLayout.DontWrapRows)
        self.SettingsLayout.setFieldGrowthPolicy(
            QFormLayout.AllNonFixedFieldsGrow)
        self.SettingsLayout.setLabelAlignment(Qt.AlignLeft)
        self.CentralLayout.addLayout(self.SettingsLayout)

        self.SettingsLayout.addRow(QLabel("Library Folder:"))
        self.SettingsLayout.addRow(self.LibraryFolderLayout)
        self.SettingsLayout.addRow(
            self.ReloadLibraryFolderContentButton)

        self.SettingsLayout.addRow(QLabel("System:"))

        if get_platform() == 'Windows':
            self.SettingsLayout.addRow(self.LaunchWhenSystemStartsCheckBox)

        self.SettingsLayout.addRow(self.LaunchMinimizedToTrayCheckBox)
        self.SettingsLayout.addRow(self.EnableHighDpiScalingCheckBox)

        self.SettingsLayout.addRow(QLabel("Interface:"))
        self.SettingsLayout.addRow(
            "Taskbar Icon Color", self.TaskbarIconColorComboBox)
        self.SettingsLayout.addRow(
            "Default Library Page", self.DefaultLibraryPageComboBox)
        self.SettingsLayout.addRow(
            "Default Downloads Page", self.DefaultDownloadsPageComboBox)

        self.SettingsLayout.addRow(QLabel("Notifications:"))
        self.SettingsLayout.addRow(self.EnableNewBuildsNotifications)
        self.SettingsLayout.addRow(self.EnableDownloadNotifications)

        self.SettingsLayout.addRow(QLabel("Service:"))
        self.SettingsLayout.addRow(
            "Mark New Build As Favorite", self.MarkAsFavorite)

        self.resize(self.sizeHint())
        self.show()
コード例 #17
0
 def clear_temp(self):
     temp_folder = Path(get_library_folder()) / ".temp"
     self.remover = Remover(temp_folder)
     self.remover.start()
コード例 #18
0
    def write_build_info(self, folder):
        # Read Blender Version
        platform = get_platform()

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

        exe_path = Path(get_library_folder()) / folder / 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:
            if platform == 'Windows':
                folder_parts = folder.name.replace("blender-", "").replace(
                    "-windows64", "").rsplit('-', 2)
            elif platform == 'Linux':
                folder_parts = folder.name.replace("blender-", "").replace(
                    "-linux64", "").rsplit('-', 2)

            if len(folder_parts) > 2:
                branch = folder_parts[0]
            elif len(folder_parts) > 1:
                branch = "daily"
            else:
                branch = "stable"
                subversion = folder_parts[0]
        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 = Path(get_library_folder()) / folder / '.blinfo'

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

        return 0
コード例 #19
0
 def register_extension(self):
     path = Path(get_library_folder()) / self.link
     self.register = Register(path)
     self.register.start()