lantool

ein feines Tool für LANs (damals)
git clone https://git.clttr.info/lantool.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

StuffItem.cs (15062B)


      1 using System;
      2 using System.Collections.Generic;
      3 using System.IO;
      4 
      5 namespace LanTool.Classes
      6 {
      7 	internal class StuffItemSorter : System.Collections.IComparer
      8 	{
      9 		public int Compare( object xx, object yy )
     10 		{
     11 			StuffItem x = ( StuffItem )( ( System.Windows.Forms.TreeNode )xx ).Tag;
     12 			StuffItem y = ( StuffItem )( ( System.Windows.Forms.TreeNode )yy ).Tag;
     13 			string xa = ( x == null ) ? "0" : ( x.IsFile ? "2" + x.Path : "1" + x.Path );
     14 			string ya = ( y == null ) ? "0" : ( y.IsFile ? "2" + y.Path : "1" + y.Path );
     15 			return String.Compare( xa, ya );
     16 		}
     17 	}
     18 
     19 	/// <summary>
     20 	/// Ein Ding des Begehrs, sei es auf der eigenen oder der fremden Platte
     21 	/// </summary>
     22 	internal class StuffItem
     23 	{
     24 		#region Parameter eines StuffItems
     25 
     26 		/// <summary>
     27 		/// Übergeordnetes StuffItem
     28 		/// </summary>
     29 		public StuffItem Parent = null;
     30 
     31 		private string _name = String.Empty;
     32 		/// <summary>
     33 		/// Name des StuffItems
     34 		/// z.B. Dateiname ohne Pfad oder Name des Verzeichnisses 
     35 		/// </summary>
     36 		public string Name
     37 		{
     38 			get
     39 			{
     40 				// Field ist noch nicht gefüllt, dann Name aus dem Dateiname oder dem Verzeichnisname ermitteln
     41 				if ( String.IsNullOrEmpty( _name ) )
     42 				{
     43 					if ( IsFile )
     44 					{
     45 						_name = System.IO.Path.GetFileName( Path );
     46 					}
     47 					else
     48 					{
     49 						_name = Path.Substring( Path.LastIndexOf( "\\" ) + 1 );
     50 					}
     51 				}
     52 
     53 				return _name;
     54 			}
     55 			private set
     56 			{
     57 				_name = value;
     58 			}
     59 
     60 		}
     61 		
     62 		/// <summary>
     63 		/// Kompletter Pfad zum StuffItems
     64 		/// </summary>
     65 		public string Path = String.Empty;
     66 
     67 		/// <summary>
     68 		/// Liste aller direkt untergeordneten StuffItems
     69 		/// </summary>
     70 		public List<StuffItem> ChildItems = new List<StuffItem>();
     71 		
     72 		/// <summary>
     73 		/// MD5-Hashwert des StuffItems
     74 		/// </summary>
     75 		public string Hash = "";
     76 		
     77 		/// <summary>
     78 		/// Dateigröße
     79 		/// </summary>
     80 		public long Size;
     81 		
     82 		/// <summary>
     83 		/// Dateigröße in lesbarer Ausgabe
     84 		/// </summary>
     85 		public string ReadableSize
     86 		{
     87 			get
     88 			{
     89 				if ( this.Size > 1024 * 1024 )
     90 					return ( ( ( double )( this.Size / 104857 ) ) / 10 ).ToString() + " MB";
     91 				else
     92 					return ( ( ( double )( this.Size / 102 ) ) / 10 ).ToString() + " KB";
     93 			}
     94 		}
     95 
     96 		/// <summary>
     97 		/// Dateigröße in Byte-Ausgabe
     98 		/// </summary>
     99 		public string LongSize
    100 		{
    101 			get
    102 			{
    103 				// Zahlenformat: mit 1000er-Punkten ohne Nachkommastellen
    104 				return String.Format( "{0:N0} Bytes", this.Size );
    105 			}
    106 		}
    107 
    108 		private bool _checked = false;
    109 		/// <summary>
    110 		/// Dateien, die markiert sind aber nicht sichtbar, werden als nicht markiert gehandhabt
    111 		/// </summary>		
    112 		public bool Checked
    113 		{
    114 			get
    115 			{
    116 				return _checked && IsVisible;
    117 			}
    118 			set
    119 			{
    120 				_checked = value;
    121 			}
    122 		}
    123 
    124 		private bool updateCheck = true;
    125 
    126 		private bool _isOnline = true;
    127 		/// <summary>
    128 		/// Online und Offline wird grundsätzlich für den ganzen Zweig darunter gesetzt
    129 		/// </summary>
    130 		public bool IsOnline
    131 		{
    132 			get
    133 			{
    134 				return _isOnline;
    135 			}
    136 			set
    137 			{
    138 				_isOnline = value;
    139 				foreach ( StuffItem si in ChildItems )
    140 					si.IsOnline = value;
    141 			}
    142 		}
    143 
    144 		/// <summary>
    145 		/// True wenn es sich um eine Datei handelt
    146 		/// </summary>
    147 		public bool IsFile = false;
    148 
    149 		/// <summary>
    150 		/// Legt das Icon für die Dateien/Ordner fest
    151 		/// </summary>
    152 		public TreeNodeImage Icon
    153 		{
    154 			get
    155 			{
    156 				if ( this.HasReadError )
    157 				{
    158 					if ( this.IsFile )
    159 					{
    160 						return TreeNodeImage.FileError;
    161 					}
    162 					else
    163 					{
    164 						return TreeNodeImage.BrokenFolder;
    165 					}
    166 				}
    167 				else if ( !this.IsFile )
    168 				{
    169 					return TreeNodeImage.Folder;
    170 				}
    171 				else if ( this.IsIgnored )
    172 				{
    173 					return TreeNodeImage.FileIngored;
    174 				}
    175 				else if ( this.IsExcluded )
    176 				{
    177 					return TreeNodeImage.FileExcluded;
    178 				}
    179 				else if ( this.HasClones )
    180 				{
    181 					return TreeNodeImage.FileRed;
    182 				}
    183 				else if ( this.IsNeeded )
    184 				{
    185 					return TreeNodeImage.FileSaugMich;
    186 				}
    187 				else if ( this.IsOnForeignDisk )
    188 				{
    189 					return TreeNodeImage.FileHabSchon;
    190 				}
    191 				else
    192 				{
    193 					return TreeNodeImage.FileWhite;
    194 				}
    195 			}
    196 		}
    197 
    198 		/// <summary>
    199 		/// Liefert den Anzeigetext für TreeNode fest
    200 		/// </summary>
    201 		public string Text
    202 		{
    203 			get
    204 			{
    205 				String dispName = Name.Substring( Name.LastIndexOf( "\\" ) + 1 );
    206 				if ( Parent == Program.MainWindow.m_MyDisks || Parent == Program.MainWindow.m_OtherDisks )
    207 				{
    208 					dispName = Name;
    209 				}
    210 
    211 				if ( IsFile && !HasReadError )
    212 				{
    213 					return String.Format( "{0} ({1})", dispName, ReadableSize );
    214 				}
    215 				else
    216 				{
    217 					return dispName;
    218 				}
    219 			}
    220 		}
    221 
    222 		/// <summary>
    223 		/// Gibt den ToolTip-Text für die Datei zurück
    224 		/// </summary>
    225 		public string ToolTip
    226 		{
    227 			get
    228 			{
    229 				if ( !this.IsFile )
    230 				{
    231 					return String.Empty;
    232 				}
    233 
    234 				string temp;
    235 
    236 				// Standardausgaben
    237 				temp = "Pfad: " + this.Path + Environment.NewLine;
    238 
    239 				// die nachfolgenden Sachen nur anzeigen, wenn keine Lesefehler vorliegen
    240 				if ( this.HasReadError )
    241 				{
    242 					temp += "Datei hat Lesefehler!";
    243 
    244 					return temp;
    245 				}
    246 
    247 				temp += "Größe: " + this.LongSize + Environment.NewLine +
    248 					"Hash: " + this.Hash + Environment.NewLine;
    249 
    250 				// bei schon auf vorhandenen Dateien auf den fremden Platten, die lokalen
    251 				// Dateien mit anzeigen
    252 				if ( IsOnForeignDisk && !IsNeeded && !IsExcluded )
    253 				{
    254 					temp += Environment.NewLine + "Meine Platten: " + Environment.NewLine +
    255 						String.Join( Environment.NewLine, this.GetLocalFiles.ToArray() );
    256 				}
    257 
    258 				// bei Dubletten auf den eigenen Platten, diese anzeigen
    259 				if ( !IsOnForeignDisk && IsFile )
    260 				{
    261 					List<StuffItem> clones = Program.MainWindow.m_MyDisks.GetItemClones( this );
    262 					if ( clones.Count > 0 )
    263 					{
    264 						temp += Environment.NewLine + "Dubletten: ";
    265 						foreach ( StuffItem csi in clones )
    266 						{
    267 							temp += Environment.NewLine + csi.Path;
    268 						}
    269 					}
    270 				}
    271 
    272 				return temp;
    273 			}
    274 		}
    275 
    276 		/// <summary>
    277 		/// Gibt an, ob die Datei im Tree sichtbar ist
    278 		/// betrifft nur tatsächliche Dateien auf fremden Platten
    279 		/// abhängig vom Status der Datei und den eingestellten Optionen
    280 		/// </summary>
    281 		public bool IsVisible
    282 		{
    283 			get
    284 			{
    285 				// wenn keine Datei oder nicht auf fremden Platten - immer sichtbar
    286 				if ( !IsFile || !IsOnForeignDisk )
    287 				{
    288 					return true;
    289 				}
    290 				else
    291 				{
    292 					// Dateien die gesperrt sind ausblenden falls Option aktiv
    293 					if ( IsExcluded && Program.MainWindow.m_Config.IsHideExcludedFiles )
    294 					{
    295 						return false;
    296 					}
    297 					// Dateien die nicht gebraucht werden ausblenden falls Option aktiv
    298 					if ( !IsExcluded && !IsNeeded && Program.MainWindow.m_Config.IsHideExistingFiles )
    299 					{
    300 						return false;
    301 					}
    302 				}
    303 
    304 				return true;
    305 			}
    306 		}
    307 
    308 		/// <summary>
    309 		/// True wenn die Datei ausgeschlossen ist
    310 		/// </summary>
    311 		public bool IsExcluded
    312 		{
    313 			get
    314 			{
    315 				return IsFile && Program.MainWindow.m_Cache.ExcludeCache.Contains( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    316 			}
    317 		}
    318 
    319 		/// <summary>
    320 		/// True wenn die Datei-Dubletten ignoriert werden
    321 		/// </summary>
    322 		public bool IsIgnored
    323 		{
    324 			get
    325 			{
    326 				return IsFile && !IsOnForeignDisk && HasClones && Program.MainWindow.m_Cache.IgnoreCache.Contains( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    327 			}
    328 		}
    329 
    330 		/// <summary>
    331 		/// Gibt an, ob beim Lesen des Verzeichnisses/der Datei ein Fehler aufgetreten ist
    332 		/// </summary>
    333 		public bool HasReadError = false;
    334 
    335 		/// <summary>
    336 		/// Gibt ab, ob sich die Datei auf einer fremden Platte befindet
    337 		/// </summary>
    338 		public bool IsOnForeignDisk = false;
    339 
    340 		/// <summary>
    341 		/// true, wenn die Datei noch nicht auf den eigenen Platten vorhanden ist und nicht
    342 		/// ausgeschlossen ist
    343 		/// </summary>
    344 		public bool IsNeeded
    345 		{
    346 			get
    347 			{
    348 				return IsFile && IsOnForeignDisk && !IsExcluded &&
    349 					( Program.MainWindow.m_MyDisks.GetRecursiveItemCount( this ) == 0 );
    350 			}
    351 		}
    352 
    353 		/// <summary>
    354 		/// Gibt alle lokalen Dateien eines StuffItems zurück
    355 		/// </summary>
    356 		public List<String> GetLocalFiles
    357 		{
    358 			get
    359 			{
    360 				List<String> localFiles = new List<String>();
    361 				if ( Program.MainWindow.m_MyDisks.GetRecursiveItemCount( this ) > 0 )
    362 				{
    363 					foreach ( StuffItem lsi in Program.MainWindow.m_MyDisks.GetItemsRecursive( this ) )
    364 					{
    365 						localFiles.Add( lsi.Path );
    366 					}
    367 				}
    368 				return localFiles;
    369 			}
    370 		}
    371 
    372 		/// <summary>
    373 		/// Gibt alle Dateien auf fremden Platten eines StuffItems zurück
    374 		/// </summary>
    375 		public List<String> GetRemoteFiles
    376 		{
    377 			get
    378 			{
    379 				List<String> remoteFiles = new List<String>();
    380 				if ( Program.MainWindow.m_OtherDisks.GetRecursiveItemCount( this ) > 0 )
    381 				{
    382 					foreach ( StuffItem lsi in Program.MainWindow.m_OtherDisks.GetItemsRecursive( this ) )
    383 					{
    384 						remoteFiles.Add( lsi.Path );
    385 					}
    386 				}
    387 				return remoteFiles;
    388 			}
    389 		}
    390 
    391 		public bool HasClones
    392 		{
    393 			get
    394 			{
    395 				return IsFile && !IsOnForeignDisk && Program.MainWindow.m_MyDisks.GetRecursiveItemCount( this ) > 1;
    396 			}
    397 		}
    398 
    399 		/// <summary>
    400 		/// Speicher für Offline-Kopie der Directory-Anfragen
    401 		/// </summary>
    402 		virtual public Dictionary<string, List<string>> OfflineDirs
    403 		{
    404 			get
    405 			{
    406 				return Parent.OfflineDirs;
    407 			}
    408 		}
    409 
    410 		/// <summary>
    411 		/// Speicher für Offline-Kopie der Files-Anfragen
    412 		/// </summary>
    413 		virtual public Dictionary<string, List<string>> OfflineFiles
    414 		{
    415 			get
    416 			{
    417 				return Parent.OfflineFiles;
    418 			}
    419 		}
    420 
    421 		/// <summary>
    422 		/// Ein StuffItem für einen (Datei-)Pfad hinzufügen, falls
    423 		/// für diesen Pfad noch keines existiert
    424 		/// </summary>
    425 		/// <param name="path">Pfad</param>
    426 		/// <returns>Das alte oder neue Item</returns>
    427 		public StuffItem AddOrGetChildItemByPath( string path )
    428 		{
    429 			// Altes Item suchen (nach Pfadnamen)
    430 			foreach ( StuffItem si in this.ChildItems )
    431 			{
    432 				if ( si.Path.Equals( path ) )
    433 				{
    434 					si.updateCheck = true;
    435 					return si;
    436 				}
    437 			}
    438 
    439 			// Neues Item einhängen, wenn das alte nicht exisitert
    440 			StuffItem new_si = new StuffItem();
    441 			new_si.IsOnForeignDisk = this.IsOnForeignDisk;
    442 			new_si.Name = path;
    443 			new_si.Path = path;
    444 			new_si.Parent = this;
    445 			new_si.IsOnline = IsOnline;
    446 			new_si.updateCheck = true;
    447 			this.ChildItems.Add( new_si );
    448 			return new_si;
    449 		}
    450 
    451 		#endregion
    452 
    453 		#region Aktionen am Item
    454 
    455 		/// <summary>
    456 		/// Datei sperren
    457 		/// </summary>
    458 		public void Exclude()
    459 		{
    460 			Program.MainWindow.m_Cache.ExcludeCache.Add( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    461 		}
    462 
    463 		/// <summary>
    464 		/// Gesperrte Datei wieder reinnehmen
    465 		/// </summary>
    466 		public void Include()
    467 		{
    468 			Program.MainWindow.m_Cache.ExcludeCache.Remove( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    469 		}
    470 
    471 		/// <summary>
    472 		/// Datei ignorieren
    473 		/// </summary>
    474 		public void Ignore()
    475 		{
    476 			Program.MainWindow.m_Cache.IgnoreCache.Add( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    477 		}
    478 
    479 		/// <summary>
    480 		/// Ignorierte Datei wieder reinnehmen
    481 		/// </summary>
    482 		public void UnIgnore()
    483 		{
    484 			Program.MainWindow.m_Cache.IgnoreCache.Remove( Program.MainWindow.m_Config.MD5FileSize + " " + this.Hash );
    485 		}
    486 
    487 		#endregion
    488 
    489 		#region Platten scannen
    490 
    491 		/// <summary>
    492 		/// ChildItems aktualisieren (background task)
    493 		/// </summary>
    494 		public void UpdateChildsBackground()
    495 		{
    496 			Program.RunBackgroundTask( this, "UpdateChilds", null );
    497 		}
    498 
    499 		/// <summary>
    500 		/// ChildItem aktualisieren und MainWindow neu aufbauen (Background Task)
    501 		/// </summary>
    502 		public void UpdateChilds( object state )
    503 		{
    504 			// Statt der RootItems alle deren Kinder scannen
    505 			if ( this == Program.MainWindow.m_MyDisks || this == Program.MainWindow.m_OtherDisks )
    506 			{
    507 				foreach ( StuffItem si in this.ChildItems.ToArray() )
    508 				{
    509 					si.ScanChilds();
    510 				}
    511 			}
    512 			else
    513 			{
    514 				this.ScanChilds();
    515 			}
    516 
    517 			// Die Caches des jeweiligen Trees aktualisieren, in der das Item aktualisiert wurde
    518 			Program.MainWindow.m_MyDisks.CreateStuffItemTreeHash();
    519 			Program.MainWindow.m_OtherDisks.CreateStuffItemTreeHash();
    520 
    521 			// Baum neu zeichnen
    522 			Program.MainWindow.UpdateTrees();
    523 		}
    524 
    525 		/// <summary>
    526 		/// ChildItems eines Items von der Platte einlesen (rekursiv) und Hash-Werte ermitteln
    527 		/// </summary>
    528 		private void ScanChilds()
    529 		{
    530 			try
    531 			{
    532 				// Alle Childs markieren, dass sie nicht aktualisiert wurden
    533 				foreach ( StuffItem si in this.ChildItems )
    534 				{
    535 					si.updateCheck = false;
    536 				}
    537 
    538 				// Verzeichnisse lesen, die nicht "excluded" durch Extension sind
    539 				string[] dirs = GetDirectories;
    540 				foreach ( string dirname in dirs )
    541 				{
    542 					if ( !Program.MainWindow.m_Config.IsDirExludedByExtension( dirname ) )
    543 					{
    544 						StuffItem si = this.AddOrGetChildItemByPath( dirname ); 
    545 						si.Path = dirname;
    546 						si.IsOnForeignDisk = this.IsOnForeignDisk;
    547 						si.ScanChilds();
    548 					}
    549 				}
    550 
    551 				// Files lesen, die nicht excluded sind. 
    552 				// Bei "restricted" extensions werden nur diese gelesen, "excluded" zählt dann nicht
    553 				string[] files = GetFiles;
    554 				foreach ( string filename in files )
    555 				{
    556 					if ( !Program.MainWindow.m_Config.IsFileExludedByExtension( filename ) )
    557 					{
    558 						StuffItem si = AddOrGetChildItemByPath( filename );
    559 						si.Path = filename;
    560 						si.IsFile = true;
    561 						si.IsOnForeignDisk = IsOnForeignDisk;
    562 						si.Hash = Program.MainWindow.m_Cache.GetHashCodeFromFileHeader( filename );
    563 						// wenn kein Hash ermittelt wurde, kann die Datei nicht gelesen werden
    564 						if ( String.IsNullOrEmpty( si.Hash ) )
    565 						{
    566 							si.HasReadError = true;
    567 						}
    568 						else
    569 						{
    570 							si.Size = Convert.ToInt64( si.Hash.Substring( 33 ), 16 );
    571 						}
    572 					}
    573 				}
    574 
    575 				// Nun alle Items wegwerfen, die kein Update hatten
    576 				for ( int i = ChildItems.Count - 1; i >= 0; i-- )
    577 				{
    578 					if ( !ChildItems[ i ].updateCheck )
    579 					{
    580 						ChildItems.RemoveAt( i );
    581 					}
    582 				}
    583 				this.HasReadError = false;
    584 			}
    585 			catch ( Exception e )
    586 			{
    587 				Program.MainWindow.LogError( "Fehler beim Einlesen: " + e.Message );
    588 				this.HasReadError = true;
    589 			}
    590 		}
    591 
    592 		/// <summary>
    593 		/// Verzeichnisse eines Pfades aus dem SimDirs oder physikalisch lesen.
    594 		/// </summary>
    595 		/// <returns></returns>
    596 		private string[] GetDirectories
    597 		{
    598 			get
    599 			{
    600 				if ( IsOnline )
    601 				{
    602 					Program.MainWindow.Status( "Lese Verzeichnis (online): " + this.Path + " " );
    603 					OfflineDirs[ Path ] = new List<string>( Directory.GetDirectories( Path ) );
    604 				}
    605 				else
    606 				{
    607 					Program.MainWindow.Status( "Lese Verzeichnis (offline): " + this.Path + " " );
    608 				}
    609 				if ( OfflineDirs.ContainsKey( Path ) )
    610 				{
    611 					return OfflineDirs[ Path ].ToArray();
    612 				}
    613 				else
    614 				{
    615 					return new string[] { };
    616 				}
    617 			}
    618 		}
    619 
    620 		/// <summary>
    621 		/// Files eines Pfades aus dem SimDirs oder physikalisch lesen.
    622 		/// </summary>
    623 		/// <returns></returns>
    624 		private string[] GetFiles
    625 		{
    626 			get
    627 			{
    628 				// bei Online-Dateien direkt von der Platte esen
    629 				if ( IsOnline )
    630 				{
    631 					OfflineFiles[ Path ] = new List<string>( Directory.GetFiles( this.Path ) );
    632 				}
    633 
    634 				// Bei Offline-Dateien die Hashcaches prüfen
    635 				if ( OfflineFiles.ContainsKey( Path ) )
    636 				{
    637 					return OfflineFiles[ Path ].ToArray();
    638 				}
    639 				else
    640 				{
    641 					return new string[] { };
    642 				}
    643 			}
    644 		}
    645 
    646 		#endregion
    647 	}
    648 }