MainForm.cs (22817B)
1 using SilkypixFileMover.Properties; 2 using SilkypixFileMover.Objects; 3 using SilkypixFileMover.Enums; 4 using System; 5 using System.Collections.Generic; 6 using System.IO; 7 using System.Linq; 8 using System.Windows.Forms; 9 using System.Text; 10 11 namespace SilkypixFileMover 12 { 13 // TODO: Texte in Ressourcen verschieben wegen Lokalisierung 14 public partial class MainForm : Form 15 { 16 List<RawFile> pendingFiles = new List<RawFile>(); 17 18 string startDir; 19 20 private History destinationDirHistory; 21 22 public MainForm() 23 { 24 InitializeComponent(); 25 26 destinationDirHistory = new History( (int)Settings.Default.DestinationDirHistoryCount ); 27 // wenn schon Verzeichnisse gespeichert sind, dann übernehmen 28 if ( Settings.Default.DestinationDirHistory != null ) 29 { 30 destinationDirHistory.EntrysAsSpecializedStringCollection = Settings.Default.DestinationDirHistory; 31 } 32 // Zielpfad vorbelegen wenn vorhanden 33 SetDestinationDirPath( Settings.Default.LastDestinationFolder ); 34 } 35 36 #region EventHandler für die Listview 37 38 private void lviFiles_SelectedIndexChanged( object sender, EventArgs e ) 39 { 40 if ( lviFiles.SelectedItems.Count > 0 ) 41 { 42 btnRemoveFile.Enabled = true; 43 } 44 else 45 { 46 btnRemoveFile.Enabled = false; 47 } 48 } 49 50 /// <summary> 51 /// Bei Doppelklick auf 1 Datei diese im Standardanzeiger öffnen 52 /// </summary> 53 /// <param name="sender"></param> 54 /// <param name="e"></param> 55 private void lviFiles_MouseDoubleClick( object sender, MouseEventArgs e ) 56 { 57 if ( e.Button == MouseButtons.Left ) 58 { 59 OpenFirstSelectedFile(); 60 } 61 } 62 63 /// <summary> 64 /// Reagiert auf Tastendrücke in der Listview 65 /// </summary> 66 /// <param name="sender"></param> 67 /// <param name="e"></param> 68 private void lviFiles_KeyUp( object sender, KeyEventArgs e ) 69 { 70 switch ( e.KeyCode ) 71 { 72 case Keys.A: 73 if ( e.Modifiers == Keys.Control ) 74 { 75 lviFiles.Items.OfType<ListViewItem>().ToList().ForEach( item => item.Selected = true ); 76 } 77 break; 78 79 case Keys.Delete: 80 RemoveSelectItemsFromListview(); 81 break; 82 83 case Keys.Enter: 84 OpenFirstSelectedFile(); 85 break; 86 } 87 } 88 89 private void RemoveSelectItemsFromListview() 90 { 91 if ( lviFiles.SelectedItems.Count > 0 ) 92 { 93 foreach ( ListViewItem item in lviFiles.SelectedItems ) 94 { 95 RawFile selectedFile = item.Tag as RawFile; 96 pendingFiles.Remove( selectedFile ); 97 } 98 99 UpdateListView(false); 100 } 101 } 102 103 /// <summary> 104 /// Fügt die übergebenen Dateien zur Liste der PendingFiles hinzu 105 /// </summary> 106 /// <param name="files">Ein Array von Dateinamen inkl. Verzeichnisangabe.</param> 107 private void AddItemsToListView(string[] files) 108 { 109 statusLabel.Text = string.Empty; 110 bool added = false; 111 foreach ( string file in files ) 112 { 113 if ( ConditionalAdd( file ) ) 114 { 115 added = true; 116 } 117 } 118 119 UpdateListView(added); 120 } 121 122 #endregion 123 124 #region Hilfsmethoden für die ListView 125 126 private void OpenFirstSelectedFile() 127 { 128 RawFile selectedFile = lviFiles.SelectedItems[ 0 ].Tag as RawFile; 129 if ( selectedFile != null ) 130 { 131 // Bild oder Datei offnen mit Pfad 132 NativeMethods.ShellExecute( 0, "open", selectedFile.RawFileFullPath, "", "", 5 ); 133 } 134 } 135 136 /// <summary> 137 /// Aktualisiert den Inhalt der ListView mit der aktuellen Dateiliste 138 /// </summary> 139 private void UpdateListView(bool showBalloon ) 140 { 141 lviFiles.SuspendLayout(); 142 lviFiles.Items.Clear(); 143 144 foreach ( RawFile dng in pendingFiles ) 145 { 146 // keine Datei-Duplikate zulassen 147 if ( lviFiles.Items.Contains( new ListViewItem( dng.RawFileName ) ) ) 148 { 149 continue; 150 } 151 152 // nach Quellverzeichnis gruppieren 153 if ( lviFiles.Groups[ dng.RawFileSourcePath ] == null ) 154 { 155 lviFiles.Groups.Add( new ListViewGroup( dng.RawFileSourcePath, dng.RawFileSourcePath ) ); 156 } 157 158 // Item hinzufügen 159 ListViewItem newItem = lviFiles.Items.Add( 160 new ListViewItem( new string[] { dng.RawFileName, dng.Size, dng.TimeStamp.ToString() }, 161 lviFiles.Groups[ dng.RawFileSourcePath ] ) ); 162 newItem.Tag = dng; 163 } 164 165 lviFiles.ResumeLayout(); 166 167 UpdateNotifyIconText(showBalloon); 168 SetActionButtonState(); 169 } 170 171 /// <summary> 172 /// Setz den Text des NotifyIcons auf den übergebenen Text oder den Standardtext 173 /// </summary> 174 /// <param name="showBalloon">Gibt an, ob der BalloonTip angezeigt werden soll oder nicht.</param> 175 private void UpdateNotifyIconText(bool showBalloon) 176 { 177 string text; 178 179 if ( pendingFiles.Count == 0 ) 180 { 181 text = "Kein Bild ausgewählt"; 182 trayIcon.Icon = Resources.backups; 183 } 184 else 185 { 186 text = string.Format( "{0} {1} ausgewählt", pendingFiles.Count, pendingFiles.Count == 1 ? "Bild" : "Bilder" ); 187 trayIcon.Icon = Resources.backup_wizard; 188 } 189 190 trayIcon.Text = string.Format( "{0} - RawFileWizard", text ); 191 if ( showBalloon ) 192 { 193 ShowBalloonTipText( text ); 194 } 195 } 196 197 /// <summary> 198 /// Zeigt eine Info mit dem übergebenen Text an 199 /// </summary> 200 /// <param name="text">Der anzuzeigende Text</param> 201 /// <param name="timeInSeconds">Anzeigedauer des Infobanners in Sekunden</param> 202 private void ShowBalloonTipText( string text, int timeInSeconds = 1 ) 203 { 204 trayIcon.BalloonTipText = text; 205 trayIcon.ShowBalloonTip( timeInSeconds * 1000 ); 206 } 207 208 #endregion 209 210 #region Eventhandler für die Buttons 211 212 /// <summary> 213 /// Button für Auswahl des Zielordners wurde angeklickt 214 /// </summary> 215 /// <param name="sender"></param> 216 /// <param name="e"></param> 217 private void btnSelectDestination_Click( object sender, EventArgs e ) 218 { 219 FolderBrowserDialog fbd = new FolderBrowserDialog(); 220 fbd.ShowNewFolderButton = true; 221 fbd.Description = "Wählen Sie das Zielverzeichnis aus:"; 222 223 // Dialog vorbelegen 224 if ( !string.IsNullOrEmpty( cboHistory.Text ) && Directory.Exists( cboHistory.Text ) ) 225 { 226 fbd.SelectedPath = cboHistory.Text; 227 } 228 229 if ( fbd.ShowDialog() == DialogResult.OK ) 230 { 231 SetDestinationDirPath( fbd.SelectedPath ); 232 } 233 } 234 235 /// <summary> 236 /// Dateien löschen 237 /// </summary> 238 /// <param name="sender"></param> 239 /// <param name="e"></param> 240 private void btnDelete_Click( object sender, EventArgs e ) 241 { 242 if ( Settings.Default.MoveToRecycleBin || 243 MessageBox.Show("Wollen sie wirklich alle gelisteten Dateien löschen?", "Dateien löschen", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2 ) == DialogResult.Yes ) 244 { 245 PrepareWorker( WorkerAction.Delete ); 246 } 247 } 248 249 /// <summary> 250 /// Dateien verschieben! 251 /// </summary> 252 /// <param name="sender"></param> 253 /// <param name="e"></param> 254 private void btnMove_Click( object sender, EventArgs e ) 255 { 256 PrepareWorker( WorkerAction.Move ); 257 } 258 259 private void PrepareWorker( WorkerAction workerAction ) 260 { 261 statusLabel.Text = string.Empty; 262 if ( !bgwWorker.IsBusy ) 263 { 264 statusProgress.Maximum = pendingFiles.Count; 265 statusProgress.Value = 0; 266 SetAllButtonState( false ); 267 268 bgwWorker.RunWorkerAsync( new WorkerParams() 269 { 270 Action = workerAction, 271 DestinationDir = cboHistory.Text 272 } ); 273 } 274 } 275 276 private void btnRemoveFile_Click( object sender, EventArgs e ) 277 { 278 RemoveSelectItemsFromListview(); 279 } 280 281 /// <summary> 282 /// Button für den Dateiauswahl-Dialog wurde gedrückt. 283 /// </summary> 284 /// <param name="sender"></param> 285 /// <param name="e"></param> 286 private void btnAddFile_Click( object sender, EventArgs e ) 287 { 288 // Parameter für den OpenFile-Dialog setzen 289 OpenFileDialog fd = new OpenFileDialog(); 290 fd.AutoUpgradeEnabled = true; 291 fd.CheckFileExists = true; 292 fd.CheckPathExists = true; 293 fd.Multiselect = true; 294 fd.ReadOnlyChecked = true; 295 fd.Title = "Bilder auswählen"; 296 fd.Filter = CreateFileFilter(); 297 298 // zuletzt verwendeten Ordner wiederherstellen 299 if ( !string.IsNullOrWhiteSpace( Settings.Default.LastSourceFolder ) ) 300 { 301 fd.InitialDirectory = Settings.Default.LastSourceFolder; 302 } 303 304 if ( string.IsNullOrWhiteSpace( fd.InitialDirectory ) ) 305 { 306 fd.InitialDirectory = Environment.GetFolderPath( Environment.SpecialFolder.MyPictures ); 307 } 308 309 if ( fd.ShowDialog() == DialogResult.OK ) 310 { 311 Settings.Default.LastSourceFolder = Path.GetDirectoryName( fd.FileName ); 312 Settings.Default.Save(); 313 314 AddItemsToListView( fd.FileNames ); 315 } 316 } 317 318 private string CreateFileFilter() 319 { 320 StringBuilder sb = new StringBuilder(); 321 sb.Append( "Bilddateien|*." ); 322 sb.Append( Settings.Default.RawFileExtension ); 323 sb.Append( ";*." ); 324 sb.Append( string.Join( ";*.", Settings.Default.JpegFileExtensions.Split( '|' ) ) ); 325 sb.Append("|Alle Dateien|*.*"); 326 return sb.ToString(); 327 } 328 329 private bool ConditionalAdd( string file ) 330 { 331 string fileExt = Path.GetExtension( file ).TrimStart( '.' ).ToLowerInvariant(); 332 333 if ( fileExt.Equals( Settings.Default.RawFileExtension.ToLowerInvariant() ) || 334 Settings.Default.JpegFileExtensions.Split( '|' ).Any( p => p.ToLowerInvariant() == fileExt ) ) 335 { 336 RawFile dng = new RawFile( file ); 337 338 // Dateien übernehmen, wenn noch nicht ausgewählt 339 if ( !pendingFiles.Contains( dng ) ) 340 { 341 pendingFiles.Add( dng ); 342 return true; 343 } 344 } 345 346 return false; 347 } 348 349 #endregion 350 351 /// <summary> 352 /// Setzt den Ziel-Pfad und aktualisiert die Buttons 353 /// </summary> 354 /// <param name="path">Pfad der gesetzt werden sollen</param> 355 private void SetDestinationDirPath( string path ) 356 { 357 if ( !string.IsNullOrEmpty( path ) ) 358 { 359 if ( !Directory.Exists( path ) ) 360 { 361 if ( MessageBox.Show( "Soll das Verzeichnis angelegt werden?", "Frage", 362 MessageBoxButtons.YesNo, 363 MessageBoxIcon.Question, 364 MessageBoxDefaultButton.Button1 ) == DialogResult.Yes ) 365 { 366 Directory.CreateDirectory( path ); 367 } 368 } 369 370 if ( Directory.Exists( path ) ) 371 { 372 cboHistory.Text = path; 373 startDir = path; 374 375 destinationDirHistory.Add( path ); 376 Settings.Default.DestinationDirHistory = destinationDirHistory.EntrysAsSpecializedStringCollection; 377 Settings.Default.LastDestinationFolder = path; 378 Settings.Default.Save(); 379 380 SetActionButtonState(); 381 return; 382 } 383 } 384 385 if ( !string.IsNullOrEmpty( startDir ) ) 386 { 387 cboHistory.Text = startDir; 388 } 389 } 390 391 /// <summary> 392 /// Aktualisiert den Status des Verschieben-Buttons je nachdem ob was ausgewählt ist 393 /// </summary> 394 private void SetActionButtonState() 395 { 396 if ( pendingFiles != null && 397 pendingFiles.Count > 0 ) 398 { 399 if ( !string.IsNullOrWhiteSpace( cboHistory.Text ) && 400 Directory.Exists( cboHistory.Text ) ) 401 { 402 btnMove.Enabled = true; 403 } 404 btnDelete.Enabled = true; 405 } 406 else 407 { 408 btnMove.Enabled = false; 409 btnDelete.Enabled = false; 410 } 411 } 412 413 private void SetAllButtonState( bool enabled ) 414 { 415 btnMove.Enabled = enabled; 416 btnDelete.Enabled = enabled; 417 btnAddFile.Enabled = enabled; 418 btnRemoveFile.Enabled = enabled; 419 btnDirUp.Enabled = enabled; 420 btnSelectDestination.Enabled = enabled; 421 cboHistory.Enabled = enabled; 422 } 423 424 #region Eventhandler für das Zielverzeichnis-Feld 425 426 private void btnDirUp_Click( object sender, EventArgs e ) 427 { 428 int index = cboHistory.Text.LastIndexOf( Path.DirectorySeparatorChar ); 429 if ( index > 0 ) 430 { 431 SetDestinationDirPath( cboHistory.Text.Substring( 0, index ) ); 432 } 433 } 434 435 private void txtDestDir_KeyUp( object sender, KeyEventArgs e ) 436 { 437 438 } 439 440 private void txtDestDir_MouseDoubleClick( object sender, MouseEventArgs e ) 441 { 442 switch ( e.Button ) 443 { 444 case MouseButtons.Right: 445 NativeMethods.ShellExecute( 0, "open", cboHistory.Text, "", "", 5 ); 446 break; 447 } 448 } 449 450 #endregion 451 452 #region Eventhandler für Drag&Drop 453 454 private void lviFiles_DragDrop( object sender, DragEventArgs e ) 455 { 456 if ( e.Data.GetDataPresent( DataFormats.FileDrop ) ) 457 { 458 try 459 { 460 string[] files = ( string[] )e.Data.GetData( DataFormats.FileDrop ); 461 AddItemsToListView( files ); 462 } 463 catch ( Exception ex ) 464 { 465 ShowBalloonTipText( ex.Message, 2 ); 466 return; 467 } 468 } 469 } 470 471 private void lviFiles_DragEnter( object sender, DragEventArgs e ) 472 { 473 if ( e.Data.GetDataPresent( DataFormats.FileDrop ) ) 474 { 475 e.Effect = DragDropEffects.Copy; 476 } 477 } 478 479 #endregion 480 481 #region Handling der Combobox 482 483 private void cboHistory_Leave( object sender, EventArgs e ) 484 { 485 cboHistory_KeyUp( sender, new KeyEventArgs( Keys.Enter ) ); 486 } 487 488 private void cboHistory_KeyUp( object sender, KeyEventArgs e ) 489 { 490 switch ( e.KeyCode ) 491 { 492 case Keys.Enter: 493 SetDestinationDirPath( cboHistory.Text ); 494 break; 495 496 case Keys.Escape: 497 SetDestinationDirPath( startDir ); 498 break; 499 } 500 } 501 502 private void cboHistory_DragEnter( object sender, DragEventArgs e ) 503 { 504 if ( e.Data.GetDataPresent( DataFormats.FileDrop ) ) 505 { 506 e.Effect = DragDropEffects.Copy; 507 } 508 } 509 510 private void cboHistory_DragDrop( object sender, DragEventArgs e ) 511 { 512 if ( e.Data.GetDataPresent( DataFormats.FileDrop ) ) 513 { 514 try 515 { 516 string[] files = ( string[] )e.Data.GetData( DataFormats.FileDrop ); 517 string path = files.FirstOrDefault(); 518 if ( !Directory.Exists( path ) ) 519 { 520 path = Path.GetDirectoryName( files.FirstOrDefault() ); 521 } 522 SetDestinationDirPath( path ); 523 } 524 catch ( Exception ex ) 525 { 526 MessageBox.Show( ex.Message, "Fehler" ); 527 return; 528 } 529 } 530 } 531 532 private void cboHistory_DropDown( object sender, EventArgs e ) 533 { 534 cboHistory.Items.Clear(); 535 cboHistory.Items.AddRange( destinationDirHistory.Entrys.Where( x => !string.IsNullOrWhiteSpace( x ) ).ToArray() ); 536 } 537 538 private void cboHistory_SelectedIndexChanged( object sender, EventArgs e ) 539 { 540 string path = ( string )cboHistory.SelectedItem; 541 542 if ( !string.IsNullOrWhiteSpace( path ) ) 543 { 544 SetDestinationDirPath( path ); 545 } 546 } 547 548 #endregion 549 550 #region Handling des BackgroundWorkers 551 552 private void bgwWorker_DoWork( object sender, System.ComponentModel.DoWorkEventArgs e ) 553 { 554 WorkerParams param = ( WorkerParams )e.Argument; 555 if ( pendingFiles != null && param.Action != WorkerAction.None ) 556 { 557 // Statusbar zurücksetzen 558 int currentProgress = 0; 559 int errorCount = 0; 560 561 List<RawFile> removeFiles = new List<RawFile>(); 562 563 // Dateien verschieben 564 foreach ( RawFile dng in pendingFiles ) 565 { 566 try 567 { 568 switch ( param.Action ) 569 { 570 case WorkerAction.Move: 571 dng.Move( param.DestinationDir ); 572 break; 573 case WorkerAction.Delete: 574 dng.Delete(); 575 break; 576 } 577 removeFiles.Add( dng ); 578 } 579 catch ( Exception ex ) 580 { 581 errorCount++; 582 string exceptionText = ex.Message; 583 // TODO: ExceptionText is too long for the status label 584 //statusLabel.Text = exceptionText; 585 ShowBalloonTipText( exceptionText, 2 ); 586 } 587 currentProgress++; 588 bgwWorker.ReportProgress( currentProgress ); 589 } 590 591 foreach ( RawFile dng in removeFiles ) 592 { 593 pendingFiles.Remove( dng ); 594 } 595 596 string okText = string.Empty; 597 string errorText = string.Empty; 598 switch ( param.Action ) 599 { 600 case WorkerAction.None: 601 break; 602 case WorkerAction.Move: 603 okText = string.Format("Alle {0} Bilder verschoben.", currentProgress ); 604 errorText = string.Format( "Von {0} Bildern konnten {1} nicht verschoben werden.", currentProgress, errorCount ); 605 break; 606 case WorkerAction.Delete: 607 okText = string.Format( "Alle {0} Bilder gelöscht.", currentProgress ); 608 errorText = string.Format("Von {0} Bildern konnten {1} nicht gelöscht werden.", currentProgress, errorCount ); 609 break; 610 } 611 612 if ( errorCount == 0 ) 613 { 614 statusLabel.Text = okText; 615 ShowBalloonTipText(okText, 1); 616 } 617 else 618 { 619 statusLabel.Text = errorText; 620 ShowBalloonTipText( errorText, 1 ); 621 } 622 } 623 } 624 625 private void bgwWorker_ProgressChanged( object sender, System.ComponentModel.ProgressChangedEventArgs e ) 626 { 627 statusProgress.Value = e.ProgressPercentage; 628 statusCounter.Text = string.Format( "Datei {0} von {1}", e.ProgressPercentage, statusProgress.Maximum ); 629 } 630 631 private void bgwWorker_RunWorkerCompleted( object sender, System.ComponentModel.RunWorkerCompletedEventArgs e ) 632 { 633 statusProgress.Value = 0; 634 statusCounter.Text = string.Empty; 635 UpdateListView(false); 636 SetAllButtonState( true ); 637 SetActionButtonState(); 638 } 639 640 #endregion 641 642 private void btnAbout_Click( object sender, EventArgs e ) 643 { 644 new About().ShowDialog(); 645 } 646 647 private void btnSettings_Click( object sender, EventArgs e ) 648 { 649 if ( new SettingsForm().ShowDialog() == DialogResult.OK ) 650 { 651 TopMost = Settings.Default.WindowTopMost; 652 } 653 } 654 655 #region Eventhandler fürs TrayIcon 656 657 private void trayIcon_DoubleClick( object sender, EventArgs e ) 658 { 659 ToogleVisibility(); 660 } 661 662 #endregion 663 664 private void beendenItem_Click( object sender, EventArgs e ) 665 { 666 Close(); 667 } 668 669 private void toogleWindowItem_Click( object sender, EventArgs e ) 670 { 671 ToogleVisibility(); 672 } 673 674 private void ToogleVisibility() 675 { 676 if ( Visible ) 677 { 678 Hide(); 679 } 680 else 681 { 682 Show(); 683 } 684 } 685 } 686 }