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()
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()])
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
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
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()
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)
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()
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)
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
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)
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)
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_()
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)
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
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