/// <summary> /// Updates internal pin data based on already updated PowerItem /// </summary> /// <param name="item">PowerItem, whose IsPinned property is already set to desired value</param> public static void PinUnpin(PowerItem item) { bool update = false; if (item.IsPinned && !PinList.Contains(item.Argument)) {//Item was pinned PinList.Add(item.Argument); update = true; } else if ((!item.IsPinned) && PinList.Contains(item.Argument)) {//Item was unpinned PinList.Remove(item.Argument); update = true; } //else means state of item may changed but already reflected in pin list if (!update) { return; } lock (LastList) { //Calculate the new index var temp = new List <MfuElement>(); LastList.ForEach(m => temp.Add(m.Clone())); temp.ApplyFiltersAndSort(); //Destination index. When moving data from LastList to StartMFU, it is truncated to contain //only 20 items with launchCount==0. So it is possible that when you unpin an element, //it's calculated position in scope of LastList will be more that StartMFU contains. //This is the fix for the problem. var tIdx = Math.Min(temp.FindIndex(mfu => mfu.Arg == item.Argument), StartMfu.Count - 1); StartMfu.Move(StartMfu.IndexOf(item), tIdx); } }
/// <summary> /// Adds an exclusion that hides MFU items that fall under it. /// Exclusions work when MFU is in P8 mode. /// </summary> /// <param name="exclusion">text to exclude from display. /// When tested for match, used with ** on both sides</param> public static void AddExclusion(PowerItem exclusion) { ExclList.Add(new StringWrapper { Value = exclusion.Argument.ToLower() }); UpdateStartMfuSync(); }
/// <summary> /// Removes item from user list. /// </summary> /// <param name="item">Item to remove. This method is called from UI, which converts /// the string paths (potentially not mapped to PowerItem originally) to new PowerItems /// when needed, so that's why there is no overload to remove string from the list.</param> public static void RemoveCustom(PowerItem item) { lock (UserList) { UserList.Remove(PowerItemTree.GetResolvedArgument(item)); _writeUserList = true; UpdateStartMfuSync(); } }
/// <summary> /// Runs the class. Starts the drive watcher thread and saves passed parameters /// </summary> /// <param name="changedHandler">Delegate to be called when a file or folder is changed/created/deleted in the system</param> /// <param name="renamedHandler">Dalegate to be called when a file or folder is renamed in the system</param> /// <param name="drivesRoot">PowerItem, under which drives list is located</param> public static void Init(FileSystemEventHandler changedHandler, RenamedEventHandler renamedHandler, PowerItem drivesRoot) { _fileChanged = changedHandler; _fileRenamed = renamedHandler; _drivesRoot = drivesRoot; SettingsManager.WatchRemovablesChanged += SettingsManagerOnWatchRemovablesChanged; Util.ForkStart(Worker, "DriveWatchThread"); Util.ForkStart(FsWorker, "File system events dequeuer"); }
/// <summary> /// Gets a string that represents a kind of tag for icon for PowerItem passed /// </summary> /// <param name="item">PowerItem which we need icon for</param> /// <param name="resolved">Resolved argument for item.</param> private static string GetObjectDescriptor(PowerItem item, string resolved) { if (item.IsFolder || item.IsSpecialObject) { return(item.NonCachedIcon ? resolved : "*"); } var rl = resolved.ToLower(); return(rl.EndsWith(".lnk") || rl.EndsWith(".exe") || rl.EndsWith(".cpl") ? resolved : Path.GetExtension(resolved)); }
public static int MoveCustomListItem(PowerItem which, PowerItem where) { lock (LastList) { //1. Change order in UserList var argFrom = PowerItemTree.GetResolvedArgument(which); var argTo = PowerItemTree.GetResolvedArgument(@where); int idxFrom = UserList.IndexOf(argFrom); int idxTo = UserList.IndexOf(argTo); UserList.RemoveAt(idxFrom); UserList.Insert(idxTo + idxFrom > idxTo ? 1 : 0, argFrom); //2. Update LastList LastList.Clear(); GetMfuFromCustomData().ForEach(m => LastList.Add(m.Clone())); //3. Change order in MfuList - with respect to pinning StartMfu.Move(StartMfu.IndexOf(which), StartMfu.IndexOf(where)); return(StartMfu.IndexOf(which)); } }
public static void Add2Custom(PowerItem item, string fullPath = null) { var arg = item == null ? fullPath : PowerItemTree.GetResolvedArgument(item); var idx = UserList.IndexOf(arg); if (idx == UserList.Count - 1 && UserList.Count > 0) //Already in list and top item { return; } if (idx != -1) //Already in list, move to top { UserList.RemoveAt(idx); } UserList.Add(arg); //Including case where item not in list if (SettingsManager.Instance.MfuIsCustom && fullPath == null) { UpdateStartMfuSync(); //Refresh } }
/// <summary> /// Synchronous getter of an icon for PowerItem /// </summary> /// <param name="item">PowerItem we need icon extracted for</param> /// <param name="iconNeeded">type of icon needed - small or large</param> /// <returns>ImageContainer with ImageSources extracted. Can be null.</returns> public static ImageContainer GetImageContainerSync(PowerItem item, API.Shgfi iconNeeded) { Log.Raw("begin>>>>>>>>>>>>>>>", item.FriendlyName); //Checking if there's cached ImageContainer string resolvedArg, descr; try { resolvedArg = PowerItemTree.GetResolvedArgument(item); descr = GetObjectDescriptor(item, resolvedArg); } catch (IOException) { return(null); } lock (Cache) { var container = (ImageContainer)(Cache.ContainsKey(descr) ? Cache[descr] : null); Log.Fmt("arg<={0}, descr<={1}, container<={2}", resolvedArg, descr, (container != null ? "not " : "") + "null"); if (container == null) //No cached instance { container = new ImageContainer(resolvedArg, descr, item.SpecialFolderId); Cache.Add(descr, container); if (iconNeeded == API.Shgfi.SMALLICON) { container.ExtractSmall(); } else { container.ExtractLarge(); } } #if DEBUG Log.Raw("end<<<<<<<<<<<<<<", item.FriendlyName); #endif return(container); } }
/// <summary> /// Returns string, of a Path kind, that can be passed to a system, and will /// represent the passed PowerItem. Depending on Caller Name, may invoke /// automatic Link resolution for Link PowerItems. "Denamespaces" the /// passed ControlPanel item returning open command for it. /// </summary> /// <param name="item">The PowerItem which has to be located/properties for /// which have to be shown.</param> /// <param name="callerName">String, the name of clicked menu item, hendler /// of which is calling this method. Recognizes "AppOpenTargetContainer" and /// "AppShowTargetProperties".</param> /// <returns>Path to binary FS object that represents the passed PowerItem or /// the target of its link.</returns> private static string Args4PropsAndCont(PowerItem item, string callerName) { string arg = null; if (item.IsControlPanelChildItem) { var executor = Util.GetOpenCommandForClass(item.Argument); if (executor != null && File.Exists(executor.Item1)) { arg = executor.Item1; } } if (arg == null) { arg = PowerItemTree.GetResolvedArgument(item); } if (item.IsLink && (callerName == "AppOpenTargetContainer" || callerName == "AppShowTargetProperties")) { arg = item.ResolvedLink; } return(arg); }
/// <summary> /// Starts asynchronous extraction of ImageContainer for PowerItem /// </summary> /// <param name="item">PowerItem we need icon extracted for</param> /// <param name="iconNeeded">type of icon needed - small or large</param> /// <returns>Always null</returns> public static ImageContainer GetImageContainer(PowerItem item, API.Shgfi iconNeeded) { ImageQueue.Enqueue(new Tuple <PowerItem, API.Shgfi>(item, iconNeeded)); return(null); }
//Same as above but inSync private static void GetRecentListForSync(PowerItem item) { string fsObject; try { fsObject = PowerItemTree.GetResolvedArgument(item); } catch (IOException) //No money no honey (no object to get JL for) { return; } IEnumerable <string> jl = null; var p8R = GetP8Recent(item.IsLink ? item.ResolvedLink : fsObject); //P8 internal JL if (Util.OsIs.SevenOrMore) //System JL { var recent = GetJumpList(fsObject, API.ADLT.RECENT); var frequent = GetJumpList(fsObject, API.ADLT.FREQUENT); if (recent != null && frequent != null) { jl = recent.Union(frequent); } else { jl = recent ?? frequent; } } if (jl != null && p8R != null) //merge everything { jl = jl.Union(p8R); } else { jl = jl ?? p8R; } if (jl == null) { return; //No jump list discovered -> nothing to do } jl = jl.Distinct() //No duplicates .Where(x => x.StartsWith("::") || File.Exists(x)) //No obsoletes .Take(25); //Not too many foreach (var arg in jl) { var local = arg; Util.Post(() => item.JumpList.Add(local.StartsWith("::") ? new PowerItem { Argument = local.Substring(2), Parent = item, SpecialFolderId = API.Csidl.POWER8JLITEM } : new PowerItem { Argument = local, Parent = item } )); } }
/// <summary> /// Updates JumpList of PowerItem passed asynchronously. JumpList is being built based on /// - system Frequent list (W7+); /// - system Recent list (W7+); /// - Power8 internal jumplist (WXP+); /// </summary> /// <param name="item">the PowerItem whose JumpList may be updated</param> public static void GetRecentListFor(PowerItem item) { Util.ForkPool(() => GetRecentListForSync(item), "MFU worker for " + item.Argument); }