def OnProjectChanged(self, event=None): changed = False if not self.ProjectDirty: changed = self.ProjectSetDirty() if DebugEnabled(): Logger.Debug(__name__, u'MainWindow.OnProjectChanged: {}'.format(changed), newline=True) print(u' Object: {}'.format(event.GetEventObject())) return changed
def ChangeWorkingDirectory(target_dir): if DebugEnabled(): Logger.Debug(__name__, u'ChangeWorkingDirectory: {}'.format(target_dir), newline=True) print(u' Working dir before: {}'.format(os.getcwd())) success = False try: os.chdir(target_dir) config_dir = ReadConfig(u'workingdir') if config_dir != target_dir: WriteConfig(u'workingdir', target_dir) success = True except OSError: # Default to the user's home directory if os.path.isdir(PATH_home): os.chdir(PATH_home) if DebugEnabled(): print(u' Working dir after: {}\n'.format(os.getcwd())) return success
def CenterOnPrimaryDisplay(window): Logger.Debug( __name__, u'Attempting to center window: {} ({})'.format(window.Name, window)) display_rect = GetPrimaryDisplayRect() Logger.Debug(__name__, u'Primary display: {}'.format(display_rect)) if not display_rect: return False window_size = window.GetSizeTuple() dx = display_rect[2] dy = display_rect[3] dw = display_rect[0] dh = display_rect[1] x_diff = (dw - window_size[0]) / 2 y_diff = (dh - window_size[1]) / 2 debug = DebugEnabled() if debug: print(u' X difference: {}'.format(x_diff)) print(u' Y difference: {}'.format(y_diff)) # NOTE: May be a few pixels off pos_x = dx + x_diff pos_y = dy + y_diff if debug: print(u'\n Theoretical position: {}'.format(( pos_x, pos_y, ))) print(u' Actual Position: {}'.format(window.GetPositionTuple())) window.SetPosition((pos_x, pos_y)) return True
def SetModeBin(self, startPage=1): self.Reset() mods = [ u'control', u'depends', u'files', u'scripts', u'changelog', u'copyright', u'launchers', u'build', ] if u'alpha' in GetTestList() or DebugEnabled(): mods.insert(3, u'manuals') for M in mods: self.AddPage(M) self.Initialize(startPage)
def __init__(self, pos, size): wx.Frame.__init__(self, None, wx.ID_ANY, default_title, pos, size) ModuleAccessCtrl.__init__(self, __name__) self.timer = DebreateTimer(self) # placeholder for progress dialog self.progress = None self.Bind(wx.EVT_TIMER, self.__onTimerEvent) self.Bind(EVT_TIMER_STOP, self.__onTimerStop) # Make sure that this frame is set as the top window if not wx.GetApp().GetTopWindow() == self: Logger.Debug(__name__, GT(u'Setting MainWindow instance as top window')) wx.GetApp().SetTopWindow(self) if DebugEnabled(): self.SetTitle(u'{} ({})'.format(default_title, GT(u'debugging'))) self.SetMinSize(wx.Size(640, 400)) # ----- Set Titlebar Icon self.SetIcon(Icon(LOGO)) # *** Status Bar *** # StatusBar(self) # *** Menus *** # createMenuBar(self) self.Wizard = Wizard(self) # *** Current Project Status *** # self.LoadedProject = None self.ProjectDirty = False # *** Event Handling *** # wx.EVT_MENU(self, menuid.NEW, self.OnProjectNew) wx.EVT_MENU(self, menuid.OPEN, self.OnProjectOpen) wx.EVT_MENU(self, menuid.SAVE, self.OnProjectSave) wx.EVT_MENU(self, menuid.SAVEAS, self.OnProjectSave) wx.EVT_MENU(self, menuid.QBUILD, self.OnQuickBuild) wx.EVT_MENU(self, menuid.EXIT, self.OnQuit) wx.EVT_MENU(self, menuid.TOOLTIPS, self.OnToggleToolTips) wx.EVT_MENU(self, menuid.DIST, self.OnUpdateDistNamesCache) wx.EVT_MENU(self, menuid.UPDATE, self.OnCheckUpdate) wx.EVT_MENU(self, menuid.HELP, self.OnHelp) wx.EVT_MENU(self, menuid.ABOUT, self.OnAbout) self.Bind(EVT_CHANGE_PAGE, self.OnWizardBtnPage) # Custom close event shows a dialog box to confirm quit wx.EVT_CLOSE(self, self.OnQuit) # *** Layout *** # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(self.Wizard, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout()
def ProjectChanged(self, event=None): if DebugEnabled(): Logger.Debug(__name__, u'MainWindow.OnProjectChanged:') print(u' Object: {}'.format(event.GetEventObject())) self.ProjectDirty = True
def OnSetLintOverrides(self, event=None): Logger.Debug(__name__, GT(u'Setting Lintian overrides...')) lintian_tags_file = u'{}/data/lintian/tags'.format(PATH_app) if not os.path.isfile(lintian_tags_file): Logger.Error( __name__, u'Lintian tags file is missing: {}'.format(lintian_tags_file)) return False lint_tags = RemoveEmptyLines(ReadFile(lintian_tags_file, split=True)) if lint_tags: Logger.Debug(__name__, u'Lintian tags set') # DEBUG: Start if DebugEnabled() and len(lint_tags) > 50: print(u' Reducing tag count to 200 ...') lint_tags = lint_tags[:50] Logger.Debug(__name__, u'Processing {} tags'.format(len(lint_tags))) # DEBUG: End tag_count = len(lint_tags) def GetProgressMessage(message, count=tag_count): return u'{} ({} {})'.format(message, count, GT(u'tags')) progress = TimedProgressDialog( GetMainWindow(), GT(u'Building Tag List'), GetProgressMessage(GT(u'Scanning default tags'))) progress.Start() wx.Yield() # Create the dialog overrides_dialog = CheckListDialog(GetMainWindow(), title=GT(u'Lintian Overrides'), allow_custom=True) # FIXME: Needs progress dialog overrides_dialog.InitCheckList(tuple(lint_tags)) progress.SetMessage( GetProgressMessage(GT(u'Setting selected overrides'))) for T in lint_tags: if T in self.lint_overrides: overrides_dialog.SetItemCheckedByLabel(T) self.lint_overrides.remove(T) progress.SetMessage( GetProgressMessage(GT(u'Adding custom tags'), len(self.lint_overrides))) # Remaining tags should be custom entries # FIXME: if self.lint_overrides: for T in self.lint_overrides: overrides_dialog.AddItem(T, True) progress.Stop() if overrides_dialog.ShowModal() == wx.ID_OK: # Remove old overrides self.lint_overrides = [] for L in overrides_dialog.GetCheckedLabels(): Logger.Debug(__name__, GT(u'Adding Lintian override: {}').format(L)) self.lint_overrides.append(L) return True else: Logger.Debug(__name__, u'Setting lintian tags failed') return False
def createMenuBar(parent): testing = u'alpha' in GetTestList() or DebugEnabled() menubar = MenuBar(parent) menu_file = wx.Menu() menubar.Append(menu_file, GT(u'File'), menuid.FILE) # This menu is filled from wiz.wizard.Wizard.SetPages menubar.Append(wx.Menu(), GT(u'Page'), menuid.PAGE) # *** File Menu *** # mitems_file = [ ( menuid.NEW, GT(u'New project'), GT(u'Start a new project'), ), ( menuid.OPEN, GT(u'Open'), GT(u'Open a previously saved project'), ), ( menuid.SAVE, GT(u'Save'), GT(u'Save current project'), ), ( menuid.SAVEAS, GT(u'Save as'), GT(u'Save current project with a new filename'), ), None, ( menuid.QBUILD, GT(u'Quick Build'), GT(u'Build a package from an existing build tree'), ICON_CLOCK, ), None, ( menuid.EXIT, GT(u'Quit'), GT(u'Exit Debreate'), ), ] if testing: mitems_file.append((menuid.ALIEN, GT(u'Convert packages'), GT(u'Convert between package types'))) # Adding all menus to menu bar mitems = (mitems_file, ) for menu_list in mitems: for mitem in menu_list: if not mitem: menu_file.AppendSeparator() else: itm = wx.MenuItem(menu_file, mitem[0], mitem[1], mitem[2]) if len(mitem) > 3: itm.SetBitmap(mitem[3]) menu_file.AppendItem(itm) # ----- Options Menu parent.menu_opt = wx.Menu() # Show/Hide tooltips parent.opt_tooltips = wx.MenuItem(parent.menu_opt, menuid.TOOLTIPS, GT(u'Show tooltips'), GT(u'Show or hide tooltips'), kind=wx.ITEM_CHECK) # A bug with wx 2.8 does not allow tooltips to be toggled off if wx.MAJOR_VERSION > 2: parent.menu_opt.AppendItem(parent.opt_tooltips) if parent.menu_opt.FindItemById(menuid.TOOLTIPS): show_tooltips = ReadConfig(u'tooltips') if show_tooltips != ConfCode.KEY_NO_EXIST: parent.opt_tooltips.Check(show_tooltips) else: parent.opt_tooltips.Check(GetDefaultConfigValue(u'tooltips')) parent.OnToggleToolTips() # *** Option Menu: open logs directory *** # if GetExecutable(u'xdg-open'): mitm_logs_open = wx.MenuItem(parent.menu_opt, menuid.OPENLOGS, GT(u'Open logs directory')) parent.menu_opt.AppendItem(mitm_logs_open) wx.EVT_MENU(parent, menuid.OPENLOGS, parent.OnLogDirOpen) # *** OS distribution names cache *** # opt_distname_cache = wx.MenuItem( parent.menu_opt, menuid.DIST, GT(u'Update dist names cache'), GT(u'Creates/Updates list of distribution names for changelog page')) parent.menu_opt.AppendItem(opt_distname_cache) mitm_ccache = wx.MenuItem(parent.menu_opt, menuid.CCACHE, GT(u'Clear local cache')) parent.menu_opt.AppendItem(mitm_ccache) # ----- Help Menu menu_help = wx.Menu() # ----- Version update mitm_update = wx.MenuItem( menu_help, menuid.UPDATE, GT(u'Check for update'), GT(u'Check if a new version is available for download')) mitm_update.SetBitmap(ICON_LOGO) menu_help.AppendItem(mitm_update) menu_help.AppendSeparator() # Menu with links to the Debian Policy Manual webpages parent.menu_policy = wx.Menu() policy_links = ( ( refid.DPM, GT(u'Debian Policy Manual'), u'https://www.debian.org/doc/debian-policy', ), ( refid.DPMCtrl, GT(u'Control files'), u'https://www.debian.org/doc/debian-policy/ch-controlfields.html', ), ( refid.DPMLog, GT(u'Changelog'), u'https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog', ), ( refid.UPM, GT(u'Ubuntu Policy Manual'), u'http://people.canonical.com/~cjwatson/ubuntu-policy/policy.html/', ), ( refid.LINT_TAGS, GT(u'Lintian Tags Explanation'), u'https://lintian.debian.org/tags-all.html', ), ( refid.LINT_OVERRIDE, GT(u'Overriding Lintian Tags'), u'https://lintian.debian.org/manual/section-2.4.html', ), ( refid.LAUNCHERS, GT(u'Launchers / Desktop entries'), u'https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/', ), # Unofficial links None, ( refid.DEBSRC, GT(u'Building debs from Source'), u'http://www.quietearth.us/articles/2006/08/16/Building-deb-package-from-source', ), # This is here only temporarily for reference ( refid.MAN, GT(u'Writing manual pages'), u'https://liw.fi/manpages/', ), ) for LINK in policy_links: if not LINK: parent.menu_policy.AppendSeparator() elif len(LINK) > 2: link_id = LINK[0] label = LINK[1] url = LINK[2] if len(LINK) > 3: icon = LINK[3] else: icon = ICON_GLOBE mitm = wx.MenuItem(parent.menu_policy, link_id, label, url) mitm.SetBitmap(icon) parent.menu_policy.AppendItem(mitm) wx.EVT_MENU(parent, link_id, parent.OpenPolicyManual) mitm_manual = wx.MenuItem(menu_help, wx.ID_HELP, GT(u'Manual'), GT(u'Open a usage document')) mitm_about = wx.MenuItem(menu_help, wx.ID_ABOUT, GT(u'About'), GT(u'About Debreate')) menu_help.AppendMenu(-1, GT(u'Reference'), parent.menu_policy) menu_help.AppendSeparator() menu_help.AppendItem(mitm_manual) menu_help.AppendItem(mitm_about) if parent.menu_opt.GetMenuItemCount(): menubar.Append(parent.menu_opt, GT(u'Options'), menuid.OPTIONS) menubar.Append(menu_help, GT(u'Help'), menuid.HELP) # catching menu events wx.EVT_MENU(parent, menuid.CCACHE, parent.OnClearCache) return menubar
def Build(self, task_list, build_path, filename): # Declare this here in case of error before progress dialog created build_progress = None try: # Other mandatory tasks that will be processed mandatory_tasks = ( u'stage', u'install_size', u'control', u'build', ) # Add other mandatory tasks for T in mandatory_tasks: task_list[T] = None task_count = len(task_list) # Add each file for updating progress dialog if u'files' in task_list: task_count += len(task_list[u'files']) # Add each script for updating progress dialog if u'scripts' in task_list: task_count += len(task_list[u'scripts']) if DebugEnabled(): task_msg = GT(u'Total tasks: {}').format(task_count) print(u'DEBUG: [{}] {}'.format(__name__, task_msg)) for T in task_list: print(u'\t{}'.format(T)) create_changelog = u'changelog' in task_list create_copyright = u'copyright' in task_list pg_control = GetPage(pgid.CONTROL) pg_menu = GetPage(pgid.MENU) stage_dir = u'{}/{}__dbp__'.format(build_path, filename) if os.path.isdir(u'{}/DEBIAN'.format(stage_dir)): try: shutil.rmtree(stage_dir) except OSError: ShowErrorDialog( GT(u'Could not free stage directory: {}').format( stage_dir), title=GT(u'Cannot Continue')) return (dbrerrno.EEXIST, None) # Actual path to new .deb deb = u'"{}/{}.deb"'.format(build_path, filename) progress = 0 task_msg = GT(u'Preparing build tree') Logger.Debug(__name__, task_msg) wx.Yield() build_progress = ProgressDialog( GetMainWindow(), GT(u'Building'), task_msg, maximum=task_count, style=PD_DEFAULT_STYLE | wx.PD_ELAPSED_TIME | wx.PD_ESTIMATED_TIME | wx.PD_CAN_ABORT) DIR_debian = ConcatPaths((stage_dir, u'DEBIAN')) # Make a fresh build tree os.makedirs(DIR_debian) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) def UpdateProgress(current_task, message=None): task_eval = u'{} / {}'.format(current_task, task_count) if message: Logger.Debug(__name__, u'{} ({})'.format(message, task_eval)) wx.Yield() build_progress.Update(current_task, message) return wx.Yield() build_progress.Update(current_task) # *** Files *** # if u'files' in task_list: UpdateProgress(progress, GT(u'Copying files')) no_follow_link = GetField(GetPage(pgid.FILES), chkid.SYMLINK).IsChecked() # TODO: move this into a file functions module def _copy(f_src, f_tgt, exe=False): # NOTE: Python 3 appears to have follow_symlinks option for shutil.copy # FIXME: copying nested symbolic link may not work if os.path.isdir(f_src): if os.path.islink(f_src) and no_follow_link: Logger.Debug( __name__, u'Adding directory symbolic link to stage: {}'. format(f_tgt)) os.symlink(os.readlink(f_src), f_tgt) else: Logger.Debug( __name__, u'Adding directory to stage: {}'.format(f_tgt)) shutil.copytree(f_src, f_tgt) os.chmod(f_tgt, 0o0755) elif os.path.isfile(f_src): if os.path.islink(f_src) and no_follow_link: Logger.Debug( __name__, u'Adding file symbolic link to stage: {}'. format(f_tgt)) os.symlink(os.readlink(f_src), f_tgt) else: if exe: Logger.Debug( __name__, u'Adding executable to stage: {}'.format( f_tgt)) else: Logger.Debug( __name__, u'Adding file to stage: {}'.format(f_tgt)) shutil.copy(f_src, f_tgt) # Set FILE permissions if exe: os.chmod(f_tgt, 0o0755) else: os.chmod(f_tgt, 0o0644) files_data = task_list[u'files'] for FILE in files_data: file_defs = FILE.split(u' -> ') source_file = file_defs[0] target_file = u'{}{}/{}'.format(stage_dir, file_defs[2], file_defs[1]) target_dir = os.path.dirname(target_file) if not os.path.isdir(target_dir): os.makedirs(target_dir) # Remove asteriks from exectuables exe = False if source_file[-1] == u'*': exe = True source_file = source_file[:-1] _copy( source_file, u'{}/{}'.format(target_dir, os.path.basename(source_file)), exe) # Individual files progress += 1 UpdateProgress(progress) # Entire file task progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Strip files ***# # FIXME: Needs only be run if 'files' step is used if u'strip' in task_list: UpdateProgress(progress, GT(u'Stripping binaries')) for ROOT, DIRS, FILES in os.walk(stage_dir): #@UnusedVariable for F in FILES: # Don't check files in DEBIAN directory if ROOT != DIR_debian: F = ConcatPaths((ROOT, F)) if FileUnstripped(F): Logger.Debug(__name__, u'Unstripped file: {}'.format(F)) # FIXME: Strip command should be set as class member? ExecuteCommand(GetExecutable(u'strip'), F) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) package = GetField(pg_control, inputid.PACKAGE).GetValue() # Make sure that the directory is available in which to place documentation if create_changelog or create_copyright: doc_dir = u'{}/usr/share/doc/{}'.format(stage_dir, package) if not os.path.isdir(doc_dir): os.makedirs(doc_dir) # *** Changelog *** # if create_changelog: UpdateProgress(progress, GT(u'Creating changelog')) # If changelog will be installed to default directory changelog_target = task_list[u'changelog'][0] if changelog_target == u'STANDARD': changelog_target = ConcatPaths( (u'{}/usr/share/doc'.format(stage_dir), package)) else: changelog_target = ConcatPaths( (stage_dir, changelog_target)) if not os.path.isdir(changelog_target): os.makedirs(changelog_target) WriteFile(u'{}/changelog'.format(changelog_target), task_list[u'changelog'][1]) CMD_gzip = GetExecutable(u'gzip') if CMD_gzip: UpdateProgress(progress, GT(u'Compressing changelog')) c = u'{} -n --best "{}/changelog"'.format( CMD_gzip, changelog_target) clog_status = commands.getstatusoutput(c.encode(u'utf-8')) if clog_status[0]: ShowErrorDialog(GT(u'Could not compress changelog'), clog_status[1], warn=True, title=GT(u'Warning')) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Copyright *** # if create_copyright: UpdateProgress(progress, GT(u'Creating copyright')) WriteFile( u'{}/usr/share/doc/{}/copyright'.format( stage_dir, package), task_list[u'copyright']) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # Characters that should not be in filenames invalid_chars = (u' ', u'/') # *** Menu launcher *** # if u'launcher' in task_list: UpdateProgress(progress, GT(u'Creating menu launcher')) # This might be changed later to set a custom directory menu_dir = u'{}/usr/share/applications'.format(stage_dir) menu_filename = pg_menu.GetOutputFilename() # Remove invalid characters from filename for char in invalid_chars: menu_filename = menu_filename.replace(char, u'_') if not os.path.isdir(menu_dir): os.makedirs(menu_dir) WriteFile(u'{}/{}.desktop'.format(menu_dir, menu_filename), task_list[u'launcher']) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** md5sums file *** # # Good practice to create hashes before populating DEBIAN directory if u'md5sums' in task_list: UpdateProgress(progress, GT(u'Creating md5sums')) if not WriteMD5(stage_dir, parent=build_progress): # Couldn't call md5sum command build_progress.Cancel() progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Scripts *** # if u'scripts' in task_list: UpdateProgress(progress, GT(u'Creating scripts')) scripts = task_list[u'scripts'] for SCRIPT in scripts: script_name = SCRIPT script_text = scripts[SCRIPT] script_filename = ConcatPaths( (stage_dir, u'DEBIAN', script_name)) WriteFile(script_filename, script_text) # Make sure scipt path is wrapped in quotes to avoid whitespace errors os.chmod(script_filename, 0755) os.system((u'chmod +x "{}"'.format(script_filename))) # Individual scripts progress += 1 UpdateProgress(progress) # Entire script task progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Control file *** # UpdateProgress(progress, GT(u'Getting installed size')) # Get installed-size installed_size = os.popen( (u'du -hsk "{}"'.format(stage_dir))).readlines() installed_size = installed_size[0].split(u'\t') installed_size = installed_size[0] # Insert Installed-Size into control file control_data = pg_control.Get().split(u'\n') control_data.insert(2, u'Installed-Size: {}'.format(installed_size)) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # Create final control file UpdateProgress(progress, GT(u'Creating control file')) # dpkg fails if there is no newline at end of file control_data = u'\n'.join(control_data).strip(u'\n') # Ensure there is only one empty trailing newline # Two '\n' to show physical empty line, but not required # Perhaps because string is not null terminated??? control_data = u'{}\n\n'.format(control_data) WriteFile(u'{}/DEBIAN/control'.format(stage_dir), control_data, noStrip=u'\n') progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Final build *** # UpdateProgress(progress, GT(u'Running dpkg')) working_dir = os.path.split(stage_dir)[0] c_tree = os.path.split(stage_dir)[1] deb_package = u'{}.deb'.format(filename) # Move the working directory becuase dpkg seems to have problems with spaces in path os.chdir(working_dir) # HACK to fix file/dir permissions for ROOT, DIRS, FILES in os.walk(stage_dir): for D in DIRS: D = u'{}/{}'.format(ROOT, D) os.chmod(D, 0o0755) for F in FILES: F = u'{}/{}'.format(ROOT, F) if os.access(F, os.X_OK): os.chmod(F, 0o0755) else: os.chmod(F, 0o0644) # FIXME: Should check for working fakeroot & dpkg-deb executables build_status = commands.getstatusoutput( (u'{} {} -b "{}" "{}"'.format(GetExecutable(u'fakeroot'), GetExecutable(u'dpkg-deb'), c_tree, deb_package))) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Delete staged directory *** # if u'rmstage' in task_list: UpdateProgress(progress, GT(u'Removing temp directory')) try: shutil.rmtree(stage_dir) except OSError: ShowErrorDialog(GT( u'An error occurred when trying to delete the build tree' ), parent=build_progress) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** ERROR CHECK if u'lintian' in task_list: UpdateProgress(progress, GT(u'Checking package for errors')) # FIXME: Should be set as class memeber? CMD_lintian = GetExecutable(u'lintian') errors = commands.getoutput((u'{} {}'.format(CMD_lintian, deb))) if errors != wx.EmptyString: e1 = GT(u'Lintian found some issues with the package.') e2 = GT(u'Details saved to {}').format(filename) WriteFile(u'{}/{}.lintian'.format(build_path, filename), errors) DetailedMessageDialog(build_progress, GT(u'Lintian Errors'), ICON_INFORMATION, u'{}\n{}.lintian'.format(e1, e2), errors).ShowModal() progress += 1 # Close progress dialog wx.Yield() build_progress.Update(progress) build_progress.Destroy() # Build completed successfullly if not build_status[0]: return (dbrerrno.SUCCESS, deb_package) if PY_VER_MAJ <= 2: # Unicode decoder has trouble with certain characters. Replace any # non-decodable characters with � (0xFFFD). build_output = list(build_status[1]) # String & unicode string incompatibilities index = 0 for C in build_output: try: GS(C) except UnicodeDecodeError: build_output[index] = u'�' index += 1 build_status = (build_status[0], u''.join(build_output)) # Build failed return (build_status[0], build_status[1]) except: if build_progress: build_progress.Destroy() return (dbrerrno.EUNKNOWN, traceback.format_exc())
def SetDepends(self, event=None): try: key_id = event.GetKeyCode() except AttributeError: key_id = event.GetEventObject().GetId() addname = self.ti_package.GetValue() oper = self.sel_operator.GetStringSelection() ver = self.ti_version.GetValue() addver = u'({}{})'.format(oper, ver) if key_id in (btnid.ADD, wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER): if TextIsEmpty(addname): return category = self.GetDefaultCategory() for C in self.categories: if C.GetValue(): category = C.GetName() break if TextIsEmpty(ver): self.AppendDependency(category, addname) else: self.AppendDependency(category, u'{} {}'.format(addname, addver)) elif key_id == btnid.APPEND: selected_count = self.lst_deps.GetSelectedItemCount() Logger.Debug(__name__, u'Appending to {} items'.format(selected_count)) if not TextIsEmpty(addname) and self.lst_deps.GetItemCount() and selected_count: selected_rows = self.lst_deps.GetSelectedIndexes() if DebugEnabled(): Logger.Debug(__name__, u'Selected rows:') for R in selected_rows: print(u'\t{}'.format(R)) for listrow in selected_rows: Logger.Debug(__name__, u'Setting list row: {}'.format(listrow)) # Get item from second column colitem = self.lst_deps.GetItem(listrow, 1) # Get the text from that item prev_text = colitem.GetText() if not TextIsEmpty(ver): new_text = u'{} | {} {}'.format(prev_text, addname, addver) else: new_text = u'{} | {}'.format(prev_text, addname) Logger.Debug(__name__, u'Appended item: {}'.format(new_text)) self.lst_deps.SetStringItem(listrow, 1, new_text) elif key_id in (btnid.REMOVE, wx.WXK_DELETE): self.lst_deps.RemoveSelected() elif key_id == btnid.CLEAR: if self.lst_deps.GetItemCount(): if ConfirmationDialog(GetMainWindow(), GT(u'Confirm'), GT(u'Clear all dependencies?')).ShowModal() in (wx.ID_OK, wx.OK): self.lst_deps.DeleteAllItems() if event: event.Skip()
if conf_values[V] in ( ConfCode.FILE_NOT_FOUND, ConfCode.KEY_NOT_DEFINED, ConfCode.KEY_NO_EXIST, ): first_run = LaunchFirstRun(debreate_app) if not first_run == ConfCode.SUCCESS: sys.exit(first_run) break Debreate = MainWindow(conf_values[u'position'], conf_values[u'size']) debreate_app.SetMainWindow(Debreate) Debreate.InitWizard() if DebugEnabled(): from ui.logwindow import LogWindow # Log window refresh interval if u'log-interval' in parsed_args_v: from ui.logwindow import SetLogWindowRefreshInterval if GS(parsed_args_v[u'log-interval']).isnumeric(): SetLogWindowRefreshInterval(int(parsed_args_v[u'log-interval'])) Debreate.SetLogWindow(LogWindow(Debreate, Logger.GetLogFile())) if conf_values[u'maximize']: Debreate.Maximize() elif conf_values[u'center']:
def ProjectOpen(self, project_file=None): Logger.Debug(__name__, u'Opening project: {}'.format(project_file)) # Need to show file open dialog because no project file was specified if not project_file: wc_z = GetDialogWildcards(ID_PROJ_Z) wc_l = GetDialogWildcards(ID_PROJ_L) wc_a = GetDialogWildcards(ID_PROJ_A) wc_t = GetDialogWildcards(ID_PROJ_T) wildcards = ( wc_a[0], wc_a[1], wc_z[0], wc_z[1], wc_t[0], wc_t[1], wc_l[0], wc_l[1], ) open_dialog = GetFileOpenDialog(self, GT(u'Open Debreate Project'), wildcards) if not ShowDialog(open_dialog): return dbrerrno.ECNCLD # Get the path and set the saved project project_file = open_dialog.GetPath() # Failsafe check that file exists if not os.path.isfile(project_file): err_l1 = GT(u'Cannot open project:') err_details = GT(u'File does not exist') ShowErrorDialog(u'{} {}'.format(err_l1, project_file), err_details) return dbrerrno.ENOENT # Check for unsaved changes & reset project to defaults if not self.ProjectClose(): return dbrerrno.ECNCLD mime_type = GetFileMimeType(project_file) Logger.Debug(__name__, GT(u'Project mime type: {}').format(mime_type)) opened = None if mime_type == u'text/plain': p_text = ReadFile(project_file) filename = os.path.split(project_file)[1] # Legacy projects should return None since we can't save in that format opened = self.ProjectOpenLegacy(p_text, filename) else: opened = self.ProjectOpenArchive(project_file, mime_type) Logger.Debug( __name__, GT(u'Project loaded before OnProjectOpen: {}').format( self.ProjectIsLoaded())) if opened == dbrerrno.SUCCESS: self.LoadedProject = project_file # Set project 'unmodified' for newly opened project self.ProjectSetDirty(False) Logger.Debug( __name__, GT(u'Project loaded after OnOpenPreject: {}').format( self.ProjectIsLoaded())) if DebugEnabled() and self.ProjectIsLoaded(): Logger.Debug(__name__, GT(u'Loaded project: {}').format(self.LoadedProject)) return opened
def __init__(self, pos, size): wx.Frame.__init__(self, None, wx.ID_ANY, default_title, pos, size) # Make sure that this frame is set as the top window if not wx.GetApp().GetTopWindow() == self: Logger.Debug(__name__, GT(u'Setting MainWindow instance as top window')) wx.GetApp().SetTopWindow(self) testing = u'alpha' in GetTestList() or DebugEnabled() if DebugEnabled(): self.SetTitle(u'{} ({})'.format(default_title, GT(u'debugging'))) self.SetMinSize(wx.Size(640, 400)) # ----- Set Titlebar Icon self.SetIcon(Icon(LOGO)) # *** Status Bar *** # StatusBar(self) # *** Menus *** # menubar = MenuBar(self) menu_file = wx.Menu() menubar.Append(menu_file, GT(u'File'), menuid.FILE) # This menu is filled from wiz.wizard.Wizard.SetPages menubar.Append(wx.Menu(), GT(u'Page'), menuid.PAGE) # *** File Menu *** # mitems_file = [ ( menuid.NEW, GT(u'New project'), GT(u'Start a new project'), ), ( menuid.OPEN, GT(u'Open'), GT(u'Open a previously saved project'), ), ( menuid.SAVE, GT(u'Save'), GT(u'Save current project'), ), ( menuid.SAVEAS, GT(u'Save as'), GT(u'Save current project with a new filename'), ), None, ( menuid.QBUILD, GT(u'Quick Build'), GT(u'Build a package from an existing build tree'), ICON_CLOCK, ), None, ( menuid.EXIT, GT(u'Quit'), GT(u'Exit Debreate'), ), ] if testing: mitems_file.append((menuid.ALIEN, GT(u'Convert packages'), GT(u'Convert between package types'))) # Adding all menus to menu bar mitems = (mitems_file, ) for menu_list in mitems: for mitem in menu_list: if not mitem: menu_file.AppendSeparator() else: itm = wx.MenuItem(menu_file, mitem[0], mitem[1], mitem[2]) if len(mitem) > 3: itm.SetBitmap(mitem[3]) menu_file.AppendItem(itm) # *** Action Menu *** # menu_action = wx.Menu() mitm_build = wx.MenuItem(menu_action, menuid.BUILD, GT(u'Build'), GT(u'Start building .deb package')) menu_action.AppendItem(mitm_build) # ----- Options Menu menu_opt = wx.Menu() # Show/Hide tooltips self.opt_tooltips = wx.MenuItem(menu_opt, menuid.TOOLTIPS, GT(u'Show tooltips'), GT(u'Show or hide tooltips'), kind=wx.ITEM_CHECK) # A bug with wx 2.8 does not allow tooltips to be toggled off if wx.MAJOR_VERSION > 2: menu_opt.AppendItem(self.opt_tooltips) if menu_opt.FindItemById(menuid.TOOLTIPS): show_tooltips = ReadConfig(u'tooltips') if show_tooltips != ConfCode.KEY_NO_EXIST: self.opt_tooltips.Check(show_tooltips) else: self.opt_tooltips.Check(GetDefaultConfigValue(u'tooltips')) self.OnToggleToolTips() # Project compression options self.menu_compress = wx.Menu() opt_z_none = wx.MenuItem( self.menu_compress, ident.ZIP_NONE, GT(u'Uncompressed'), GT(u'Use uncompressed tarball for project save format'), kind=wx.ITEM_RADIO) opt_z_gz = wx.MenuItem( self.menu_compress, ident.ZIP_GZ, GT(u'Gzip'), GT(u'Use compressed Gzip tarball for project save format'), kind=wx.ITEM_RADIO) opt_z_bz2 = wx.MenuItem( self.menu_compress, ident.ZIP_BZ2, GT(u'Bzip2'), GT(u'Use compressed Bzip2 tarball for project save format'), kind=wx.ITEM_RADIO) opt_z_zip = wx.MenuItem( self.menu_compress, ident.ZIP_ZIP, GT(u'Zip'), GT(u'Use compressed zip file for project save format'), kind=wx.ITEM_RADIO) opts_compress = [ opt_z_none, opt_z_gz, opt_z_bz2, opt_z_zip, ] if GetExecutable(u'tar') != None: opt_z_xz = wx.MenuItem( self.menu_compress, ident.ZIP_XZ, GT(u'XZ'), GT(u'Use compressed xz tarball for project save format'), kind=wx.ITEM_RADIO) opts_compress.insert(3, opt_z_xz) for OPT in opts_compress: self.menu_compress.AppendItem(OPT) wx.EVT_MENU(self.menu_compress, OPT.GetId(), self.OnSetCompression) # Default compression self.menu_compress.Check(ident.ZIP_BZ2, True) menu_opt.AppendSubMenu( self.menu_compress, GT(u'Project Compression'), GT(u'Set the compression type for project save output')) # *** Option Menu: open logs directory *** # if GetExecutable(u'xdg-open'): mitm_logs_open = wx.MenuItem(menu_opt, menuid.OPENLOGS, GT(u'Open logs directory')) menu_opt.AppendItem(mitm_logs_open) wx.EVT_MENU(menu_opt, menuid.OPENLOGS, self.OnLogDirOpen) # *** OS distribution names cache *** # opt_distname_cache = wx.MenuItem( menu_opt, menuid.DIST, GT(u'Update dist names cache'), GT(u'Creates/Updates list of distribution names for changelog page' )) menu_opt.AppendItem(opt_distname_cache) # ----- Help Menu menu_help = wx.Menu() # ----- Version update mitm_update = wx.MenuItem( menu_help, menuid.UPDATE, GT(u'Check for update'), GT(u'Check if a new version is available for download')) mitm_update.SetBitmap(ICON_LOGO) menu_help.AppendItem(mitm_update) menu_help.AppendSeparator() # Menu with links to the Debian Policy Manual webpages self.menu_policy = wx.Menu() policy_links = ( ( refid.DPM, GT(u'Debian Policy Manual'), u'https://www.debian.org/doc/debian-policy', ), ( refid.DPMCtrl, GT(u'Control files'), u'https://www.debian.org/doc/debian-policy/ch-controlfields.html', ), ( refid.DPMLog, GT(u'Changelog'), u'https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog', ), ( refid.UPM, GT(u'Ubuntu Policy Manual'), u'http://people.canonical.com/~cjwatson/ubuntu-policy/policy.html/', ), ( refid.LINT_TAGS, GT(u'Lintian Tags Explanation'), u'https://lintian.debian.org/tags-all.html', ), ( refid.LINT_OVERRIDE, GT(u'Overriding Lintian Tags'), u'https://lintian.debian.org/manual/section-2.4.html', ), ( refid.LAUNCHERS, GT(u'Launchers / Desktop entries'), u'https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/', ), # Unofficial links None, ( refid.DEBSRC, GT(u'Building debs from Source'), u'http://www.quietearth.us/articles/2006/08/16/Building-deb-package-from-source', ), # This is here only temporarily for reference ( refid.MAN, GT(u'Writing manual pages'), u'https://liw.fi/manpages/', ), ) for LINK in policy_links: if not LINK: self.menu_policy.AppendSeparator() elif len(LINK) > 2: link_id = LINK[0] label = LINK[1] url = LINK[2] if len(LINK) > 3: icon = LINK[3] else: icon = ICON_GLOBE mitm = wx.MenuItem(self.menu_policy, link_id, label, url) mitm.SetBitmap(icon) self.menu_policy.AppendItem(mitm) wx.EVT_MENU(self, link_id, self.OpenPolicyManual) mitm_help = wx.MenuItem(menu_help, wx.ID_HELP, GT(u'Help'), GT(u'Open a usage document')) mitm_about = wx.MenuItem(menu_help, wx.ID_ABOUT, GT(u'About'), GT(u'About Debreate')) menu_help.AppendMenu(-1, GT(u'Reference'), self.menu_policy) menu_help.AppendSeparator() menu_help.AppendItem(mitm_help) menu_help.AppendItem(mitm_about) menubar.Append(menu_action, GT(u'Action'), menuid.ACTION) if menu_opt.GetMenuItemCount(): menubar.Append(menu_opt, GT(u'Options'), menuid.OPTIONS) menubar.Append(menu_help, GT(u'Help'), menuid.HELP) self.Wizard = Wizard(self) # Menu for debugging & running tests if DebugEnabled(): self.menu_debug = wx.Menu() menubar.Append(self.menu_debug, GT(u'Debug'), menuid.DEBUG) self.menu_debug.AppendItem( wx.MenuItem(self.menu_debug, menuid.LOG, GT(u'Show log'), GT(u'Toggle debug log window'), kind=wx.ITEM_CHECK)) if u'log-window' in parsed_args_s: self.menu_debug.Check(menuid.LOG, True) self.log_window = None # Window colors self.menu_debug.AppendItem( wx.MenuItem(self.menu_debug, menuid.THEME, GT(u'Toggle window colors'))) wx.EVT_MENU(self, menuid.THEME, self.OnToggleTheme) # *** Current Project Status *** # self.LoadedProject = None self.ProjectDirty = False self.dirty_mark = u' *' menu_file.Enable(wx.ID_SAVE, self.ProjectDirty) # *** Event Handling *** # wx.EVT_MENU(self, menuid.NEW, self.OnProjectNew) wx.EVT_MENU(self, menuid.OPEN, self.OnProjectOpen) wx.EVT_MENU(self, menuid.SAVE, self.OnProjectSave) wx.EVT_MENU(self, menuid.SAVEAS, self.OnProjectSaveAs) wx.EVT_MENU(self, menuid.QBUILD, self.OnQuickBuild) wx.EVT_MENU(self, menuid.EXIT, self.OnQuit) wx.EVT_MENU(self, menuid.TOOLTIPS, self.OnToggleToolTips) wx.EVT_MENU(self, menuid.DIST, self.OnUpdateDistNamesCache) wx.EVT_MENU(self, menuid.UPDATE, self.OnCheckUpdate) wx.EVT_MENU(self, menuid.HELP, self.OnHelp) wx.EVT_MENU(self, menuid.ABOUT, self.OnAbout) self.Bind(EVT_CHANGE_PAGE, self.OnWizardBtnPage) # Custom close event shows a dialog box to confirm quit wx.EVT_CLOSE(self, self.OnQuit) # *** Layout *** # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(self.Wizard, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout()
def SetLauncherData(self, data, enabled=True): # Make sure we are dealing with a list if isinstance(data, (unicode, str)): data = data.split(u'\n') # Data list is not empty if data: Logger.Debug(__name__, u'Loading launcher') if data[0].isnumeric(): enabled = int(data.pop(0)) > 0 if DebugEnabled(): for L in data: print(u' Launcher line: {}'.format(L)) Logger.Debug(__name__, u'Enabling launcher: {}'.format(enabled)) if enabled: GetField(self, chkid.ENABLE).SetValue(True) data_defs = {} data_defs_remove = [] misc_defs = [] for L in data: if u'=' in L: if L[0] == u'[' and L[-1] == u']': key = L[1:-1].split(u'=') value = key[1] key = key[0] misc_defs.append(u'{}={}'.format(key, value)) else: key = L.split(u'=') value = key[1] key = key[0] data_defs[key] = value # Fields using SetValue() function set_value_fields = ( (u'Name', GetField(self, inputid.NAME)), (u'Exec', GetField(self, inputid.EXEC)), (u'Comment', GetField(self, inputid.DESCR)), (u'Icon', GetField(self, inputid.ICON)), (u'Type', GetField(self, inputid.TYPE)), (u'Encoding', GetField(self, inputid.ENC)), ) for label, control in set_value_fields: try: control.SetValue(data_defs[label]) data_defs_remove.append(label) except KeyError: pass check_box_fields = ( (u'Terminal', GetField(self, chkid.TERM)), (u'StartupNotify', GetField(self, chkid.NOTIFY)), ) for label, control in check_box_fields: try: if data_defs[label].lower() == u'true': control.SetValue(True) else: control.SetValue(False) data_defs_remove.append(label) except KeyError: pass try: lst_categories = GetField(self, listid.CAT) categories = tuple(data_defs[u'Categories'].split(u';')) for C in categories: lst_categories.InsertStringItem( lst_categories.GetItemCount(), C) data_defs_remove.append(u'Categories') except KeyError: pass for K in data_defs_remove: if K in data_defs: del data_defs[K] # Add any leftover keys to misc/other for K in data_defs: if K not in (u'Version', ): misc_defs.append(u'{}={}'.format(K, data_defs[K])) for index in reversed(range(len(misc_defs))): K = misc_defs[index] # Set custom filename if u'FILENAME=' in K: filename = K.replace(u'FILENAME=', u'') if not TextIsEmpty(filename): Logger.Debug( __name__, u'Setting custom filename: {}'.format( filename)) GetField(self, inputid.FNAME).SetValue(filename) GetField(self, chkid.FNAME).SetValue(False) # Remove so not added to misc. list misc_defs.pop(index) continue if misc_defs: GetField(self, inputid.OTHER).SetValue(u'\n'.join( sorted(misc_defs))) self.OnToggle()
def Set(self, data): # Make sure we are dealing with a list if isinstance(data, (unicode, str)): data = data.split(u'\n') # Data list is not empty if data: Logger.Debug(__name__, u'Loading launcher') if DebugEnabled(): for L in data: print(u' Launcher line: {}'.format(L)) data_defs = {} data_defs_remove = [] misc_defs = [] for L in data: if u'=' in L: if L[0] == u'[' and L[-1] == u']': key = L[1:-1].split(u'=') value = key[1] key = key[0] misc_defs.append(u'{}={}'.format(key, value)) else: key = L.split(u'=') value = key[1] key = key[0] data_defs[key] = value # Fields using SetValue() function set_value_fields = ( (u'Name', GetField(self, inputid.NAME)), (u'Exec', GetField(self, inputid.EXEC)), (u'Comment', GetField(self, inputid.DESCR)), (u'Icon', GetField(self, inputid.ICON)), (u'Type', GetField(self, inputid.TYPE)), (u'Encoding', GetField(self, inputid.ENC)), ) for label, control in set_value_fields: try: control.SetValue(data_defs[label]) data_defs_remove.append(label) except KeyError: pass # Fields using SetSelection() function set_selection_fields = ( (u'Terminal', self.sel_term), (u'StartupNotify', self.sel_notify), ) for label, control in set_selection_fields: try: control.SetStringSelection(data_defs[label].lower()) data_defs_remove.append(label) except KeyError: pass try: lst_categories = GetField(self, listid.CAT) categories = tuple(data_defs[u'Categories'].split(u';')) for C in categories: lst_categories.InsertStringItem( lst_categories.GetItemCount(), C) data_defs_remove.append(u'Categories') except KeyError: pass for K in data_defs_remove: if K in data_defs: del data_defs[K] # Add any leftover keys to misc/other for K in data_defs: if K not in (u'Version', ): misc_defs.append(u'{}={}'.format(K, data_defs[K])) for index in reversed(range(len(misc_defs))): K = misc_defs[index] # Set custom filename if u'FILENAME=' in K: filename = K.replace(u'FILENAME=', u'') # Remove so not added to misc. list misc_defs.pop(index) continue '''