func (job *GetAllLaunchAppsJob) Execute() {
	job.op.ListenDone(func(e error) {
		defer dbus.UnInstallObject(job)
		if e != nil {
			dbus.Emit(job, "Done", e.Error())
			return
		}

		apps := job.op.Result().([]*gio.AppInfo)
		info := LaunchAppInfo{
			Names: make([]string, len(apps)),
			Ids:   make([]string, len(apps)),
		}
		for i, app := range apps {
			info.Names[i] = app.GetName()
			info.Ids[i] = app.GetId()
			// TODO: get icon
			// app.GetIcon()
			app.Unref()
		}

		bInfos, err := json.Marshal(info)
		if err != nil {
			dbus.Emit(job, "Done", err.Error())
			return
		}

		dbus.Emit(job, "LaunchAppInfo", string(bInfos))
		dbus.Emit(job, "Done", "")
	})
	job.op.Execute()
}
// Execute list job.
func (job *ListJob) Execute() []operations.ListProperty {
	defer dbus.UnInstallObject(job)
	var files []operations.ListProperty
	job.op.ListenProcessedAmount(func(size int64, unit operations.AmountUnit) {
		dbus.Emit(job, "ProcessedAmount", size, uint16(unit))
	})
	job.op.ListenProperty(func(property operations.ListProperty) {
		dbus.Emit(job, "EntryInfo", property)
		files = append(files, property)
	})
	job.op.ListenDone(func(err error) {
		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}
		// time.Sleep(time.Microsecond * 200)
		dbus.Emit(job, "Done", errMsg)
	})
	job.op.ListenAborted(func() {
		defer dbus.UnInstallObject(job)
		dbus.Emit(job, "Aborted")
	})
	job.op.Execute()

	return files
}
// Execute GetDefaultLaunchAppJob.
func (job *GetDefaultLaunchAppJob) Execute() {
	job.op.ListenDone(func(err error) {
		defer dbus.UnInstallObject(job)
		if err != nil {
			dbus.Emit(job, "Done", err.Error())
			return
		}

		app := job.op.Result().(*gio.AppInfo)
		info := &DefaultLaunchAppInfo{
			Name: app.GetName(),
			Id:   app.GetId(),
			// TODO: get icon.
			// Icon: getIconFromApp(app),
		}
		app.Unref()
		bInfos, err := json.Marshal(info)
		if err != nil {
			dbus.Emit(job, "Done", err.Error())
			return
		}

		dbus.Emit(job, "DefaultLaunchAppInfo", string(bInfos))
		dbus.Emit(job, "Done", "")
	})
	job.op.Execute()
}
// Execute stat job.
func (job *StatJob) Execute() {
	job.op.ListenDone(func(err error) {
		defer dbus.UnInstallObject(job)
		if err != nil {
			dbus.Emit(job, "Done", err.Error())
			return
		}

		dbus.Emit(job, "Stat", job.op.Result().(operations.StatProperty))
		dbus.Emit(job, "Done", "")
	})
	job.op.Execute()
}
func (job *RenameJob) Execute() {
	defer dbus.UnInstallObject(job)
	job.op.ListenDone(func(err error) {
		var errMsg = ""
		if err != nil {
			errMsg = err.Error()
		}
		dbus.Emit(job, "Done", errMsg)
	})
	job.op.ListenOldName(func(oldName string) {
		dbus.Emit(job, "OldName", oldName)
	})
	job.op.ListenNewFile(func(fileURL string) {
		dbus.Emit(job, "NewFile", fileURL)
	})
	job.op.Execute()
}
// Execute trash job.
func (job *TrashJob) Execute() {
	job.op.ListenProcessedAmount(func(size int64, unit operations.AmountUnit) {
		dbus.Emit(job, "ProcessedAmount", size, uint16(unit))
	})
	job.op.ListenPercent(func(percent int64) {
		dbus.Emit(job, "ProcessedPercent", percent)
	})
	job.op.ListenAborted(func() {
		defer dbus.UnInstallObject(job)
		dbus.Emit(job, "Aborted")
	})
	job.op.ListenDone(func(err error) {
		dbus.Emit(job, "Done")
	})
	// TODO: fill signals.
	defer dbus.UnInstallObject(job)
	job.op.Execute()
}
func (job *DeleteJob) listenSignals() {
	job.op.ListenTotalAmount(func(amount int64, unit operations.AmountUnit) {
		dbus.Emit(job, "TotalAmount", amount, uint16(unit))
	})
	job.op.ListenProcessedAmount(func(size int64, unit operations.AmountUnit) {
		dbus.Emit(job, "ProcessedAmount", size, uint16(unit))
	})
	job.op.ListenPercent(func(percent int64) {
		dbus.Emit(job, "ProcessedPercent", percent)
	})

	job.op.ListenDeleting(func(deletingURL string) {
		dbus.Emit(job, "Deleting", deletingURL)
	})
	job.op.ListenAborted(func() {
		defer dbus.UnInstallObject(job)
		dbus.Emit(job, "Aborted")
	})
}
// Execute chmod job.
func (job *ChmodJob) Execute() {
	job.op.ListenDone(func(err error) {
		defer dbus.UnInstallObject(job)
		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}
		dbus.Emit(job, "Done", errMsg)
	})
	job.op.Execute()
}
func (job *CopyJob) listenSignals() {
	job.op.ListenTotalAmount(func(amount int64, unit operations.AmountUnit) {
		dbus.Emit(job, "TotalAmount", amount, uint16(unit))
	})
	job.op.ListenProcessedAmount(func(amount int64, unit operations.AmountUnit) {
		dbus.Emit(job, "ProcessedAmount", amount, uint16(unit))
	})
	job.op.ListenPercent(func(percent int64) {
		dbus.Emit(job, "ProcessedPercent", percent)
	})
	job.op.ListenCopying(func(srcURL string) {
		Log.Debug("copying", srcURL)
		dbus.Emit(job, "Copying", srcURL)
	})
	job.op.ListenCreatingDir(func(dirURL string) {
		// TODO
		// dbus.Emit(job, "CreatingDir", dirURL)
	})
	job.op.ListenCopyingMovingDone(func(srcURL string, destURL string) {
	})
	job.op.ListenDone(func(err error) {
		defer dbus.UnInstallObject(job)
		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}
		dbus.Emit(job, "Done", errMsg)
	})
	job.op.ListenAborted(func() {
		defer dbus.UnInstallObject(job)
		dbus.Emit(job, "Aborted")
	})
}
func NewWatcher(id uint32, fileURI string) (*Watcher, error) {
	fsWatcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}

	if err := fsWatcher.Watch(fileURI); err != nil {
		fsWatcher.Close()
		return nil, err
	}

	watcher := &Watcher{
		ID:      WatcherID(id),
		watcher: fsWatcher,
		end:     make(chan struct{}),
	}
	watcher.dbusInfo = dbus.DBusInfo{
		Dest:       "com.deepin.filemanager.Backend.Watcher",
		ObjectPath: fmt.Sprintf("/com/deepin/filemanager/Backend/Watcher/%d", watcher.ID),
		Interface:  "com.deepin.filemanager.Backend.Watcher",
	}

	go func() {
		for {
			select {
			case ev := <-fsWatcher.Event:
				var event uint32
				switch {
				case ev.IsAttrib():
					event = FsNotifyAttributeChanged
				case ev.IsCreate():
					event = FsNotifyCreated
				case ev.IsDelete():
					event = FsNotifyDeleted
				case ev.IsModify():
					event = FsNotifyModified
				case ev.IsRename():
					event = FsNotifyRename
				}
				dbus.Emit(watcher, "Changed", ev.Name, event)
			case err := <-fsWatcher.Error:
				Log.Warning("fsWatcher error:", err)
				return
			case <-watcher.end:
				return
			}
		}
	}()

	return watcher, nil
}
// Execute create job.
func (job *CreateJob) Execute() {
	go func() {
		defer dbus.UnInstallObject(job)
		err := job.op.Execute()
		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}

		dbus.Emit(job, "Done", job.op.Result().(string), errMsg)
		// TODO:
		// job.commandRecorder
		// operations.FileUndoManagerInstance().RecordJob(create, job.op)
	}()
}
func NewTrashMonitor() (*TrashMonitor, error) {
	trashMonitor := new(TrashMonitor)
	trash := gio.FileNewForUri("trash://")
	trashMonitor.trash = trash
	monitor, err := trash.MonitorDirectory(gio.FileMonitorFlagsNone, nil)
	if err != nil {
		return nil, err
	}

	trashMonitor.monitor = monitor
	monitor.Connect("changed", func(*gio.FileMonitor, *gio.File, *gio.File, gio.FileMonitorEvent) {
		// TODO: seperate trash monitor and dbus into two parts.
		dbus.Emit(trashMonitor, "ItemCountChanged", trashMonitor.ItemCount())
	})

	return trashMonitor, nil
}
func (c *Clipboard) EmitPaste(file string) {
	contents := operations.GetClipboardContents()
	if len(contents) < 2 {
		Log.Warning("invalid content or empty content in clipboard")
		return
	}

	op := contents[0]
	files := contents[1:]

	switch op {
	case operations.OpCut:
		fallthrough
	case operations.OpCopy:
		dbus.Emit(c, "RequestPaste", op, files, file)
	default:
		Log.Warning("not valid operation")
	}
}
func NewMonitor(id uint32, fileURI string, flags gio.FileMonitorFlags) (*Monitor, error) {
	file := gio.FileNewForCommandlineArg(fileURI)
	if file == nil {
		return nil, fmt.Errorf("create file from %s failed\n", fileURI)
	}

	monitor := &Monitor{
		file:        file,
		cancellable: gio.NewCancellable(),
		flags:       flags,
		ID:          id,
	}

	monitor.dbusInfo = dbus.DBusInfo{
		Dest:       "com.deepin.filemanager.Backend.Monitor",
		ObjectPath: fmt.Sprintf("/com/deepin/filemanager/Backend/Monitor/%d", monitor.ID),
		Interface:  "com.deepin.filemanager.Backend.Monitor",
	}

	var err error
	monitor.monitor, err = monitor.file.Monitor(flags, monitor.cancellable)
	if err != nil {
		monitor.finalize()
		return nil, fmt.Errorf("create file monitor failed: %s", err)
	}
	monitor.monitor.Connect("changed", func(m *gio.FileMonitor, file *gio.File, newFile *gio.File, events gio.FileMonitorEvent) {
		newFileURI := ""
		if newFile != nil {
			newFileURI = newFile.GetUri()
		}
		err := dbus.Emit(monitor, "Changed", file.GetUri(), newFileURI, uint32(events))
		if err != nil {
			Log.Warning("emit signal failed:", err)
		}
	})

	return monitor, nil
}
func (s *Settings) emitThunbnailSizeLimitationChanged(size uint64) error {
	return dbus.Emit(s, "ThumbnailSizeLimitationChanged", size)
}
func (s *Settings) emitIconZoomLevelChanged(level int32) error {
	return dbus.Emit(s, "IconZoomLevelChanged", level)
}
// Abort the job.
func (job *CopyJob) Abort() {
	job.op.Abort()
	dbus.Emit(job, "Aborted")
}
func (s *Settings) emitShowComputerIconChanged(enable bool) error {
	return dbus.Emit(s, "ShowComputerIconChanged", enable)
}
func (job *EmptyTrashJob) executeJob() {
	defer dbus.UnInstallObject(job)
	job.op.Execute()
	dbus.Emit(job, "Done")
}
// Abort the job.
func (job *MoveJob) Abort() {
	job.op.Abort()
	dbus.Emit(job, "Aborted")
}
func (s *Settings) emitAutoArrangementChanged(enable bool) error {
	return dbus.Emit(s, "AutoArrangementChanged", enable)
}
func (s *Settings) emitLabelPositionChanged(position string) error {
	return dbus.Emit(s, "LabelPositionChanged", position)
}
func (s *Settings) emitShowExtensionNameChanged(enable bool) error {
	return dbus.Emit(s, "ShowExtensionNameChanged", enable)
}
func (s *Settings) emitShowHiddenFilesChanged(enable bool) error {
	return dbus.Emit(s, "ShowHiddenFilesChanged", enable)
}
func (s *Settings) emitShowThumbnailChanged(showPolicy string) error {
	return dbus.Emit(s, "ShowThumbnailChanged", showPolicy)
}
func (s *Settings) emitClickPolicyChanged(clickPolicy string) error {
	return dbus.Emit(s, "ClickPolicyChanged", clickPolicy)
}
func (s *Settings) emitConfirmEmptyTrashChanged(enable bool) error {
	return dbus.Emit(s, "ConfirmEmptyTrashChanged", enable)
}
func (s *Settings) emitAllowDeleteImmediatlyChanged(enable bool) error {
	return dbus.Emit(s, "AllowDeleteImmediatlyChanged", enable)
}
func (s *Settings) emitActivationPolicyChanged(activationPolicy string) error {
	return dbus.Emit(s, "ActivationPolicyChanged", activationPolicy)
}
func (s *Settings) emitStickupGridChanged(enable bool) error {
	return dbus.Emit(s, "StickupGridChanged", enable)
}