2017-09-05 05:27:55 +00:00
#define LOADALL
using System ;
2016-12-30 02:11:51 +00:00
using System.Collections.Concurrent ;
2015-10-06 01:51:52 +00:00
using System.Collections.Generic ;
using System.Diagnostics ;
2015-12-20 00:29:44 +00:00
using System.Drawing ;
2015-10-06 01:51:52 +00:00
using System.IO ;
using System.Linq ;
2016-12-29 23:24:02 +00:00
using System.Threading.Tasks ;
2015-10-06 01:51:52 +00:00
using System.Windows.Forms ;
2017-01-08 07:54:09 +00:00
using PKHeX.Core ;
2017-05-23 04:55:05 +00:00
using PKHeX.WinForms.Controls ;
2015-10-06 01:51:52 +00:00
2017-01-08 07:54:09 +00:00
namespace PKHeX.WinForms
2015-10-06 01:51:52 +00:00
{
public partial class SAV_Database : Form
{
2017-05-23 04:55:05 +00:00
private readonly SaveFile SAV ;
private readonly SAVEditor BoxView ;
private readonly PKMEditor PKME_Tabs ;
public SAV_Database ( PKMEditor f1 , SAVEditor saveditor )
2015-10-06 01:51:52 +00:00
{
2017-05-23 04:55:05 +00:00
SAV = saveditor . SAV ;
BoxView = saveditor ;
PKME_Tabs = f1 ;
2015-10-06 01:51:52 +00:00
InitializeComponent ( ) ;
2016-07-10 17:33:01 +00:00
// Preset Filters to only show PKM available for loaded save
CB_FormatComparator . SelectedIndex = 3 ; // <=
2015-10-08 03:19:34 +00:00
PKXBOXES = new [ ]
{
bpkx1 , bpkx2 , bpkx3 , bpkx4 , bpkx5 , bpkx6 ,
bpkx7 , bpkx8 , bpkx9 , bpkx10 , bpkx11 , bpkx12 ,
bpkx13 , bpkx14 , bpkx15 , bpkx16 , bpkx17 , bpkx18 ,
bpkx19 , bpkx20 , bpkx21 , bpkx22 , bpkx23 , bpkx24 ,
bpkx25 , bpkx26 , bpkx27 , bpkx28 , bpkx29 , bpkx30 ,
bpkx31 , bpkx32 , bpkx33 , bpkx34 , bpkx35 , bpkx36 ,
bpkx37 , bpkx38 , bpkx39 , bpkx40 , bpkx41 , bpkx42 ,
bpkx43 , bpkx44 , bpkx45 , bpkx46 , bpkx47 , bpkx48 ,
bpkx49 , bpkx50 , bpkx51 , bpkx52 , bpkx53 , bpkx54 ,
bpkx55 , bpkx56 , bpkx57 , bpkx58 , bpkx59 , bpkx60 ,
bpkx61 , bpkx62 , bpkx63 , bpkx64 , bpkx65 , bpkx66 ,
} ;
// Enable Scrolling when hovered over
foreach ( var slot in PKXBOXES )
{
// Enable Click
2017-07-06 01:39:53 +00:00
slot . MouseClick + = ( sender , e ) = >
2015-10-08 03:19:34 +00:00
{
if ( ModifierKeys = = Keys . Control )
2017-07-06 01:39:53 +00:00
ClickView ( sender , e ) ;
2015-11-15 03:41:39 +00:00
else if ( ModifierKeys = = Keys . Alt )
2017-07-06 01:39:53 +00:00
ClickDelete ( sender , e ) ;
2015-11-15 03:41:39 +00:00
else if ( ModifierKeys = = Keys . Shift )
2017-07-06 01:39:53 +00:00
ClickSet ( sender , e ) ;
2015-10-08 03:19:34 +00:00
} ;
}
Counter = L_Count . Text ;
2015-10-12 07:10:40 +00:00
Viewed = L_Viewed . Text ;
L_Viewed . Text = "" ; // invis for now
2017-07-06 01:39:53 +00:00
var hover = new ToolTip ( ) ;
L_Viewed . MouseEnter + = ( sender , e ) = > hover . SetToolTip ( L_Viewed , L_Viewed . Text ) ;
2017-06-18 01:37:19 +00:00
PopulateComboBoxes ( ) ;
2015-10-08 03:19:34 +00:00
ContextMenuStrip mnu = new ContextMenuStrip ( ) ;
ToolStripMenuItem mnuView = new ToolStripMenuItem ( "View" ) ;
2015-11-15 02:17:54 +00:00
ToolStripMenuItem mnuDelete = new ToolStripMenuItem ( "Delete" ) ;
2015-10-08 03:19:34 +00:00
// Assign event handlers
2017-06-18 01:37:19 +00:00
mnuView . Click + = ClickView ;
mnuDelete . Click + = ClickDelete ;
2015-10-08 03:19:34 +00:00
// Add to main context menu
2015-11-15 02:17:54 +00:00
mnu . Items . AddRange ( new ToolStripItem [ ] { mnuView , mnuDelete } ) ;
2015-10-08 03:19:34 +00:00
// Assign to datagridview
foreach ( PictureBox p in PKXBOXES )
p . ContextMenuStrip = mnu ;
2015-10-06 01:51:52 +00:00
2016-08-03 00:40:20 +00:00
// Load Data
2017-09-05 05:22:02 +00:00
B_Search . Enabled = false ;
L_Count . Text = "Loading..." ;
new Task ( LoadDatabase ) . Start ( ) ;
2016-08-03 00:40:20 +00:00
2016-03-23 03:30:48 +00:00
Menu_SearchSettings . DropDown . Closing + = ( sender , e ) = >
2016-03-23 03:14:11 +00:00
{
if ( e . CloseReason = = ToolStripDropDownCloseReason . ItemClicked )
e . Cancel = true ;
} ;
2016-04-15 23:11:46 +00:00
CenterToParent ( ) ;
2015-10-06 01:51:52 +00:00
}
2017-05-23 04:55:05 +00:00
2016-01-17 21:27:24 +00:00
private readonly PictureBox [ ] PKXBOXES ;
private readonly string DatabasePath = Main . DatabasePath ;
2016-06-20 04:22:43 +00:00
private List < PKM > Results ;
private List < PKM > RawDB ;
2015-10-10 17:28:24 +00:00
private int slotSelected = - 1 ; // = null;
2015-12-20 00:29:44 +00:00
private Image slotColor ;
2015-10-10 17:28:24 +00:00
private const int RES_MAX = 66 ;
private const int RES_MIN = 6 ;
2016-01-17 21:27:24 +00:00
private readonly string Counter ;
private readonly string Viewed ;
2016-11-13 01:56:45 +00:00
private const int MAXFORMAT = 7 ;
2017-06-10 06:13:41 +00:00
private readonly string EXTERNAL_SAV = new DirectoryInfo ( Main . BackupPath ) . Name + Path . DirectorySeparatorChar ;
2017-06-18 01:37:19 +00:00
private static string Hash ( PKM pk )
2017-01-14 20:10:42 +00:00
{
switch ( pk . Format )
{
2017-09-30 05:58:25 +00:00
case 1 : return $"{pk.Species:000}{((PK1) pk).DV16:X4}" ;
case 2 : return $"{pk.Species:000}{((PK2) pk).DV16:X4}" ;
default : return $"{pk.Species:000}{pk.PID:X8}{string.Join(" ", pk.IVs)}{pk.AltForm:00}" ;
2017-01-14 20:10:42 +00:00
}
2017-05-13 17:20:25 +00:00
}
2015-10-06 01:51:52 +00:00
2015-10-10 17:28:24 +00:00
// Important Events
2017-06-18 01:37:19 +00:00
private void ClickView ( object sender , EventArgs e )
2015-10-06 01:51:52 +00:00
{
2016-02-01 07:15:54 +00:00
sender = ( ( sender as ToolStripItem ) ? . Owner as ContextMenuStrip ) ? . SourceControl ? ? sender as PictureBox ;
int index = Array . IndexOf ( PKXBOXES , sender ) ;
2017-04-19 10:15:50 +00:00
if ( index > = RES_MAX )
{
2015-10-08 03:19:34 +00:00
System . Media . SystemSounds . Exclamation . Play ( ) ;
2017-04-19 10:15:50 +00:00
return ;
}
index + = SCR_Box . Value * RES_MIN ;
if ( index > = Results . Count )
2015-10-08 03:19:34 +00:00
{
2017-04-19 10:15:50 +00:00
System . Media . SystemSounds . Exclamation . Play ( ) ;
return ;
2015-10-08 03:19:34 +00:00
}
2017-04-19 10:15:50 +00:00
2017-06-18 01:37:19 +00:00
PKME_Tabs . PopulateFields ( Results [ index ] , false ) ;
2017-04-19 10:15:50 +00:00
slotSelected = index ;
2017-05-12 04:34:18 +00:00
slotColor = Properties . Resources . slotView ;
2017-04-19 10:15:50 +00:00
FillPKXBoxes ( SCR_Box . Value ) ;
L_Viewed . Text = string . Format ( Viewed , Results [ index ] . Identifier ) ;
2015-10-06 01:51:52 +00:00
}
2017-06-18 01:37:19 +00:00
private void ClickDelete ( object sender , EventArgs e )
2015-11-15 02:17:54 +00:00
{
2016-02-01 07:15:54 +00:00
sender = ( ( sender as ToolStripItem ) ? . Owner as ContextMenuStrip ) ? . SourceControl ? ? sender as PictureBox ;
int index = Array . IndexOf ( PKXBOXES , sender ) ;
2017-04-19 10:15:50 +00:00
if ( index > = RES_MAX )
{
2015-11-15 02:17:54 +00:00
System . Media . SystemSounds . Exclamation . Play ( ) ;
2017-04-19 10:15:50 +00:00
return ;
}
index + = SCR_Box . Value * RES_MIN ;
if ( index > = Results . Count )
{
System . Media . SystemSounds . Exclamation . Play ( ) ;
return ;
}
var pk = Results [ index ] ;
string path = pk . Identifier ;
2017-09-05 05:27:55 +00:00
#if LOADALL
2017-06-10 06:13:41 +00:00
if ( path . StartsWith ( EXTERNAL_SAV ) )
{
WinFormsUtil . Alert ( "Can't delete from a backup save." ) ;
return ;
}
#endif
2017-04-19 10:15:50 +00:00
if ( path . Contains ( Path . DirectorySeparatorChar ) )
{
// Data from Database: Delete file from disk
2017-06-10 06:13:41 +00:00
if ( File . Exists ( path ) )
File . Delete ( path ) ;
2017-04-19 10:15:50 +00:00
}
2015-11-15 02:17:54 +00:00
else
{
2017-04-19 10:15:50 +00:00
// Data from Box: Delete from save file
int box = pk . Box - 1 ;
int slot = pk . Slot - 1 ;
2017-06-18 01:37:19 +00:00
int offset = SAV . GetBoxOffset ( box ) + slot * SAV . SIZE_STORED ;
PKM pkSAV = SAV . GetStoredSlot ( offset ) ;
2015-11-15 02:17:54 +00:00
2018-01-27 18:15:56 +00:00
if ( ! pkSAV . DecryptedBoxData . SequenceEqual ( pk . DecryptedBoxData ) ) // data still exists in SAV, unmodified
2015-11-15 02:17:54 +00:00
{
2017-04-19 10:15:50 +00:00
WinFormsUtil . Error ( "Database slot data does not match save data!" , "Don't move Pokémon after initializing the Database, please re-open the Database viewer." ) ;
return ;
2015-11-15 02:17:54 +00:00
}
2017-06-11 18:08:03 +00:00
var change = new SlotChange { Box = box , Offset = offset , Slot = slot } ;
BoxView . M . SetPKM ( BoxView . SAV . BlankPKM , change , true , Properties . Resources . slotDel ) ;
2015-11-15 02:17:54 +00:00
}
2017-04-19 10:15:50 +00:00
// Remove from database.
RawDB . Remove ( pk ) ;
Results . Remove ( pk ) ;
// Refresh database view.
L_Count . Text = string . Format ( Counter , Results . Count ) ;
slotSelected = - 1 ;
FillPKXBoxes ( SCR_Box . Value ) ;
System . Media . SystemSounds . Asterisk . Play ( ) ;
2015-11-15 02:17:54 +00:00
}
2017-06-18 01:37:19 +00:00
private void ClickSet ( object sender , EventArgs e )
2015-11-15 03:41:39 +00:00
{
// Don't care what slot was clicked, just add it to the database
2017-06-18 01:37:19 +00:00
if ( ! PKME_Tabs . VerifiedPKM ( ) )
2015-11-15 03:41:39 +00:00
return ;
2017-06-18 01:37:19 +00:00
PKM pk = PKME_Tabs . PreparePKM ( ) ;
2017-10-03 06:13:40 +00:00
Directory . CreateDirectory ( DatabasePath ) ;
2015-11-15 03:41:39 +00:00
string path = Path . Combine ( DatabasePath , Util . CleanFileName ( pk . FileName ) ) ;
if ( RawDB . Any ( p = > p . Identifier = = path ) )
{
2017-01-08 07:54:09 +00:00
WinFormsUtil . Alert ( "File already exists in database!" ) ;
2015-11-15 03:41:39 +00:00
return ;
}
2016-06-20 04:22:43 +00:00
File . WriteAllBytes ( path , pk . Data . Take ( pk . SIZE_STORED ) . ToArray ( ) ) ;
2015-11-15 03:41:39 +00:00
pk . Identifier = path ;
2015-12-20 00:29:44 +00:00
int pre = RawDB . Count ;
2015-11-15 03:41:39 +00:00
RawDB . Add ( pk ) ;
2017-04-19 10:15:50 +00:00
RawDB = new List < PKM > ( RawDB ) ;
2015-12-20 00:29:44 +00:00
int post = RawDB . Count ;
if ( pre = = post )
2017-01-08 07:54:09 +00:00
{ WinFormsUtil . Alert ( "Pokémon already exists in database." ) ; return ; }
2015-11-15 03:41:39 +00:00
Results . Add ( pk ) ;
2015-12-20 00:29:44 +00:00
2015-11-15 03:41:39 +00:00
// Refresh database view.
2016-02-01 07:15:54 +00:00
L_Count . Text = string . Format ( Counter , Results . Count ) ;
2015-12-20 00:29:44 +00:00
slotSelected = Results . Count - 1 ;
2017-05-12 04:34:18 +00:00
slotColor = Properties . Resources . slotSet ;
2015-12-20 00:29:44 +00:00
if ( ( SCR_Box . Maximum + 1 ) * 6 < Results . Count )
SCR_Box . Maximum + = 1 ;
2015-12-20 00:32:22 +00:00
SCR_Box . Value = Math . Max ( 0 , SCR_Box . Maximum - PKXBOXES . Length / 6 + 1 ) ;
2015-11-15 03:41:39 +00:00
FillPKXBoxes ( SCR_Box . Value ) ;
2017-01-08 07:54:09 +00:00
WinFormsUtil . Alert ( "Added Pokémon from tabs to database." ) ;
2015-11-15 03:41:39 +00:00
}
2017-06-18 01:37:19 +00:00
private void PopulateComboBoxes ( )
2015-10-08 03:19:34 +00:00
{
// Set the Text
CB_HeldItem . DisplayMember =
CB_Species . DisplayMember =
CB_Ability . DisplayMember =
CB_Nature . DisplayMember =
CB_GameOrigin . DisplayMember =
CB_HPType . DisplayMember = "Text" ;
2015-10-06 01:51:52 +00:00
2015-10-08 03:19:34 +00:00
// Set the Value
CB_HeldItem . ValueMember =
CB_Species . ValueMember =
CB_Ability . ValueMember =
CB_Nature . ValueMember =
CB_GameOrigin . ValueMember =
CB_HPType . ValueMember = "Value" ;
2016-07-09 22:34:38 +00:00
var Any = new ComboItem { Text = "Any" , Value = - 1 } ;
2015-10-08 03:19:34 +00:00
2016-10-29 22:41:55 +00:00
var DS_Species = new List < ComboItem > ( GameInfo . SpeciesDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Species . RemoveAt ( 0 ) ; DS_Species . Insert ( 0 , Any ) ; CB_Species . DataSource = DS_Species ;
2016-10-29 22:41:55 +00:00
var DS_Item = new List < ComboItem > ( GameInfo . ItemDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Item . Insert ( 0 , Any ) ; CB_HeldItem . DataSource = DS_Item ;
2016-10-29 22:41:55 +00:00
var DS_Nature = new List < ComboItem > ( GameInfo . NatureDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Nature . Insert ( 0 , Any ) ; CB_Nature . DataSource = DS_Nature ;
2016-10-29 22:41:55 +00:00
var DS_Ability = new List < ComboItem > ( GameInfo . AbilityDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Ability . Insert ( 0 , Any ) ; CB_Ability . DataSource = DS_Ability ;
2016-10-29 22:41:55 +00:00
var DS_Version = new List < ComboItem > ( GameInfo . VersionDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Version . Insert ( 0 , Any ) ; CB_GameOrigin . DataSource = DS_Version ;
2017-01-08 07:54:09 +00:00
string [ ] hptypes = new string [ GameInfo . Strings . types . Length - 2 ] ; Array . Copy ( GameInfo . Strings . types , 1 , hptypes , 0 , hptypes . Length ) ;
2017-06-18 01:37:19 +00:00
var DS_Type = Util . GetCBList ( hptypes , null ) ;
2015-10-08 03:19:34 +00:00
DS_Type . Insert ( 0 , Any ) ; CB_HPType . DataSource = DS_Type ;
// Set the Move ComboBoxes too..
2016-10-29 22:41:55 +00:00
var DS_Move = new List < ComboItem > ( GameInfo . MoveDataSource ) ;
2015-10-08 03:19:34 +00:00
DS_Move . RemoveAt ( 0 ) ; DS_Move . Insert ( 0 , Any ) ;
{
foreach ( ComboBox cb in new [ ] { CB_Move1 , CB_Move2 , CB_Move3 , CB_Move4 } )
{
cb . DisplayMember = "Text" ; cb . ValueMember = "Value" ;
cb . DataSource = new BindingSource ( DS_Move , null ) ;
}
}
// Trigger a Reset
2017-06-18 01:37:19 +00:00
ResetFilters ( null , null ) ;
2015-10-08 03:19:34 +00:00
}
2017-06-18 01:37:19 +00:00
private void ResetFilters ( object sender , EventArgs e )
2015-10-06 01:51:52 +00:00
{
2015-10-08 03:19:34 +00:00
CHK_Shiny . Checked = CHK_IsEgg . Checked = true ;
CHK_Shiny . CheckState = CHK_IsEgg . CheckState = CheckState . Indeterminate ;
MT_ESV . Text = "" ;
CB_HeldItem . SelectedIndex = 0 ;
CB_Species . SelectedIndex = 0 ;
CB_Ability . SelectedIndex = 0 ;
CB_Nature . SelectedIndex = 0 ;
CB_HPType . SelectedIndex = 0 ;
2015-10-06 01:51:52 +00:00
2015-10-08 03:19:34 +00:00
CB_Level . SelectedIndex = 0 ;
TB_Level . Text = "" ;
CB_EVTrain . SelectedIndex = 0 ;
CB_IV . SelectedIndex = 0 ;
2015-10-06 01:51:52 +00:00
2015-10-08 03:19:34 +00:00
CB_Move1 . SelectedIndex = CB_Move2 . SelectedIndex = CB_Move3 . SelectedIndex = CB_Move4 . SelectedIndex = 0 ;
CB_GameOrigin . SelectedIndex = 0 ;
2015-10-10 17:28:24 +00:00
CB_Generation . SelectedIndex = 0 ;
2015-10-12 07:12:21 +00:00
MT_ESV . Visible = L_ESV . Visible = false ;
2016-07-23 08:04:55 +00:00
RTB_Instructions . Clear ( ) ;
2016-01-18 01:11:32 +00:00
if ( sender ! = null )
System . Media . SystemSounds . Asterisk . Play ( ) ;
2015-10-06 01:51:52 +00:00
}
2017-06-18 01:37:19 +00:00
private void GenerateDBReport ( object sender , EventArgs e )
2015-10-11 01:29:02 +00:00
{
2017-01-08 07:54:09 +00:00
if ( WinFormsUtil . Prompt ( MessageBoxButtons . YesNo , "Generate a Report on all data?" , "This may take a while..." )
2015-10-11 01:29:02 +00:00
! = DialogResult . Yes )
return ;
2017-06-18 01:37:19 +00:00
ReportGrid reportGrid = new ReportGrid ( ) ;
reportGrid . Show ( ) ;
reportGrid . PopulateData ( Results . ToArray ( ) ) ;
2015-10-11 01:29:02 +00:00
}
2015-10-08 03:19:34 +00:00
2017-09-05 05:22:02 +00:00
private void LoadDatabase ( )
{
var dbTemp = new ConcurrentBag < PKM > ( ) ;
2017-09-24 00:02:28 +00:00
var files = Directory . EnumerateFiles ( DatabasePath , "*" , SearchOption . AllDirectories ) ;
2017-09-05 05:22:02 +00:00
Parallel . ForEach ( files , file = >
{
FileInfo fi = new FileInfo ( file ) ;
if ( ! fi . Extension . Contains ( ".pk" ) | | ! PKX . IsPKM ( fi . Length ) ) return ;
2017-09-29 05:20:27 +00:00
var pk = PKMConverter . GetPKMfromBytes ( File . ReadAllBytes ( file ) , file , prefer : ( fi . Extension . Last ( ) - '0' ) & 0xF ) ;
2017-09-05 05:22:02 +00:00
if ( pk ! = null )
dbTemp . Add ( pk ) ;
} ) ;
2017-09-05 05:27:55 +00:00
#if LOADALL
2017-09-05 05:22:02 +00:00
if ( SaveUtil . GetSavesFromFolder ( Main . BackupPath , false , out IEnumerable < string > result ) )
{
Parallel . ForEach ( result , file = >
{
var sav = SaveUtil . GetVariantSAV ( File . ReadAllBytes ( file ) ) ;
var path = EXTERNAL_SAV + new FileInfo ( file ) . Name ;
if ( sav . HasBox )
foreach ( var pk in sav . BoxData )
addPKM ( pk ) ;
void addPKM ( PKM pk )
{
pk . Identifier = Path . Combine ( path , pk . Identifier ) ;
dbTemp . Add ( pk ) ;
}
} ) ;
}
#endif
// Prepare Database
RawDB = new List < PKM > ( dbTemp . OrderBy ( pk = > pk . Identifier )
. Concat ( SAV . BoxData . Where ( pk = > pk . Species ! = 0 ) ) // Fetch from save file
. Where ( pk = > pk . ChecksumValid & & pk . Species ! = 0 & & pk . Sanity = = 0 )
. Distinct ( ) ) ;
2018-01-25 17:17:39 +00:00
// Load stats for pkm who do not have any
foreach ( var pk in RawDB . Where ( z = > z . Stat_Level = = 0 ) )
2018-01-28 22:11:12 +00:00
{
pk . Stat_Level = pk . CurrentLevel ;
2018-01-25 17:17:39 +00:00
pk . SetStats ( pk . GetStats ( pk . PersonalInfo ) ) ;
2018-01-28 22:11:12 +00:00
}
2018-01-25 17:17:39 +00:00
2017-11-11 03:43:31 +00:00
try
{
BeginInvoke ( new MethodInvoker ( ( ) = > SetResults ( RawDB ) ) ) ;
}
catch { /* Window Closed? */ }
2017-09-05 05:22:02 +00:00
}
2015-10-10 17:28:24 +00:00
// IO Usage
2017-06-18 01:37:19 +00:00
private void OpenDB ( object sender , EventArgs e )
2015-10-06 01:51:52 +00:00
{
if ( Directory . Exists ( DatabasePath ) )
2016-07-17 17:06:52 +00:00
Process . Start ( "explorer.exe" , DatabasePath ) ;
2015-10-06 01:51:52 +00:00
}
2015-10-13 00:12:20 +00:00
private void Menu_Export_Click ( object sender , EventArgs e )
{
if ( Results = = null | | Results . Count = = 0 )
2017-01-08 07:54:09 +00:00
{ WinFormsUtil . Alert ( "No results to export." ) ; return ; }
2015-10-13 00:12:20 +00:00
2017-01-08 07:54:09 +00:00
if ( DialogResult . Yes ! = WinFormsUtil . Prompt ( MessageBoxButtons . YesNo , "Export to a folder?" ) )
2015-10-13 00:12:20 +00:00
return ;
FolderBrowserDialog fbd = new FolderBrowserDialog ( ) ;
if ( DialogResult . OK ! = fbd . ShowDialog ( ) )
return ;
string path = fbd . SelectedPath ;
2017-10-03 06:13:40 +00:00
Directory . CreateDirectory ( path ) ;
2015-10-13 00:12:20 +00:00
2016-06-20 04:22:43 +00:00
foreach ( PKM pkm in Results )
2016-08-03 00:40:20 +00:00
File . WriteAllBytes ( Path . Combine ( path , Util . CleanFileName ( pkm . FileName ) ) , pkm . DecryptedBoxData ) ;
2015-10-13 00:12:20 +00:00
}
2018-02-02 01:29:07 +00:00
private void Menu_Import_Click ( object sender , EventArgs e )
{
if ( ! BoxView . GetBulkImportSettings ( out var clearAll , out var noSetb ) )
return ;
int box = BoxView . Box . CurrentBox ;
if ( ! SAV . LoadBoxes ( Results , out var result , box , clearAll , noSetb ) )
return ;
BoxView . SetPKMBoxes ( ) ;
BoxView . UpdateBoxViewers ( ) ;
WinFormsUtil . Alert ( result ) ;
}
2015-10-08 03:19:34 +00:00
2015-10-10 17:28:24 +00:00
// View Updates
2017-05-30 02:18:18 +00:00
private IEnumerable < PKM > SearchDatabase ( )
2015-10-08 03:19:34 +00:00
{
// Populate Search Query Result
2016-06-20 04:22:43 +00:00
IEnumerable < PKM > res = RawDB ;
2015-10-08 03:19:34 +00:00
2017-06-11 18:08:03 +00:00
// Filter for Selected Source
if ( ! Menu_SearchBoxes . Checked )
res = res . Where ( pk = > pk . Identifier . StartsWith ( DatabasePath + Path . DirectorySeparatorChar , StringComparison . Ordinal ) ) ;
if ( ! Menu_SearchDatabase . Checked )
{
res = res . Where ( pk = > ! pk . Identifier . StartsWith ( DatabasePath + Path . DirectorySeparatorChar , StringComparison . Ordinal ) ) ;
2017-09-05 05:27:55 +00:00
#if LOADALL
2017-06-11 18:08:03 +00:00
res = res . Where ( pk = > ! pk . Identifier . StartsWith ( EXTERNAL_SAV , StringComparison . Ordinal ) ) ;
#endif
}
2016-06-28 04:16:46 +00:00
int format = MAXFORMAT + 1 - CB_Format . SelectedIndex ;
2016-07-10 17:33:01 +00:00
switch ( CB_FormatComparator . SelectedIndex )
{
case 0 : /* Do nothing */ break ;
case 1 : res = res . Where ( pk = > pk . Format > = format ) ; break ;
case 2 : res = res . Where ( pk = > pk . Format = = format ) ; break ;
case 3 : res = res . Where ( pk = > pk . Format < = format ) ; break ;
}
2016-09-16 02:04:43 +00:00
if ( CB_FormatComparator . SelectedIndex ! = 0 )
{
if ( format < = 2 ) // 1-2
res = res . Where ( pk = > pk . Format < = 2 ) ;
if ( format > = 3 & & format < = 6 ) // 3-6
res = res . Where ( pk = > pk . Format > = 3 ) ;
}
2016-06-28 04:16:46 +00:00
switch ( CB_Generation . SelectedIndex )
{
2016-07-10 17:33:01 +00:00
case 0 : /* Do nothing */ break ;
2016-11-13 01:56:45 +00:00
case 1 : res = res . Where ( pk = > pk . Gen7 ) ; break ;
case 2 : res = res . Where ( pk = > pk . Gen6 ) ; break ;
case 3 : res = res . Where ( pk = > pk . Gen5 ) ; break ;
case 4 : res = res . Where ( pk = > pk . Gen4 ) ; break ;
case 5 : res = res . Where ( pk = > pk . Gen3 ) ; break ;
2016-06-28 04:16:46 +00:00
}
2015-10-08 03:19:34 +00:00
// Primary Searchables
2017-06-18 01:37:19 +00:00
int species = WinFormsUtil . GetIndex ( CB_Species ) ;
int ability = WinFormsUtil . GetIndex ( CB_Ability ) ;
int nature = WinFormsUtil . GetIndex ( CB_Nature ) ;
int item = WinFormsUtil . GetIndex ( CB_HeldItem ) ;
2015-10-08 03:19:34 +00:00
if ( species ! = - 1 ) res = res . Where ( pk = > pk . Species = = species ) ;
if ( ability ! = - 1 ) res = res . Where ( pk = > pk . Ability = = ability ) ;
if ( nature ! = - 1 ) res = res . Where ( pk = > pk . Nature = = nature ) ;
if ( item ! = - 1 ) res = res . Where ( pk = > pk . HeldItem = = item ) ;
// Secondary Searchables
2017-06-18 01:37:19 +00:00
int move1 = WinFormsUtil . GetIndex ( CB_Move1 ) ;
int move2 = WinFormsUtil . GetIndex ( CB_Move2 ) ;
int move3 = WinFormsUtil . GetIndex ( CB_Move3 ) ;
int move4 = WinFormsUtil . GetIndex ( CB_Move4 ) ;
2017-09-30 05:58:25 +00:00
var moves = new [ ] { move1 , move2 , move3 , move4 } . Where ( z = > z > 0 ) . ToList ( ) ;
int count = moves . Count ;
if ( count > 0 ) res = res . Where ( pk = > pk . Moves . Intersect ( moves ) . Count ( ) = = count ) ;
2017-06-18 01:37:19 +00:00
int vers = WinFormsUtil . GetIndex ( CB_GameOrigin ) ;
2015-10-08 03:19:34 +00:00
if ( vers ! = - 1 ) res = res . Where ( pk = > pk . Version = = vers ) ;
2017-06-18 01:37:19 +00:00
int hptype = WinFormsUtil . GetIndex ( CB_HPType ) ;
2015-10-08 03:19:34 +00:00
if ( hptype ! = - 1 ) res = res . Where ( pk = > pk . HPType = = hptype ) ;
if ( CHK_Shiny . CheckState = = CheckState . Checked ) res = res . Where ( pk = > pk . IsShiny ) ;
if ( CHK_Shiny . CheckState = = CheckState . Unchecked ) res = res . Where ( pk = > ! pk . IsShiny ) ;
if ( CHK_IsEgg . CheckState = = CheckState . Checked ) res = res . Where ( pk = > pk . IsEgg ) ;
if ( CHK_IsEgg . CheckState = = CheckState . Unchecked ) res = res . Where ( pk = > ! pk . IsEgg ) ;
2018-01-25 16:54:29 +00:00
if ( CHK_IsEgg . CheckState = = CheckState . Checked & & int . TryParse ( MT_ESV . Text , out int esv ) )
res = res . Where ( pk = > pk . PSV = = esv ) ;
2015-10-08 03:19:34 +00:00
// Tertiary Searchables
2017-08-25 01:49:09 +00:00
res = FilterByLVL ( res , CB_Level . SelectedIndex , TB_Level . Text ) ;
res = FilterByIVs ( res , CB_IV . SelectedIndex ) ;
res = FilterByEVs ( res , CB_EVTrain . SelectedIndex ) ;
2015-10-08 03:19:34 +00:00
2015-10-09 13:34:26 +00:00
slotSelected = - 1 ; // reset the slot last viewed
2017-08-25 01:49:09 +00:00
2017-03-18 23:50:34 +00:00
if ( Menu_SearchLegal . Checked & & ! Menu_SearchIllegal . Checked )
res = res . Where ( pk = > new LegalityAnalysis ( pk ) . ParsedValid ) ;
if ( ! Menu_SearchLegal . Checked & & Menu_SearchIllegal . Checked )
res = res . Where ( pk = > new LegalityAnalysis ( pk ) . ParsedInvalid ) ;
2016-03-16 04:10:33 +00:00
2016-07-23 08:04:55 +00:00
if ( RTB_Instructions . Lines . Any ( line = > line . Length > 0 ) )
{
2017-06-18 01:37:19 +00:00
var filters = BatchEditor . StringInstruction . GetFilters ( RTB_Instructions . Lines ) . ToArray ( ) ;
BatchEditor . ScreenStrings ( filters ) ;
2017-09-30 05:58:25 +00:00
res = res . Where ( pkm = > IsPKMFiltered ( pkm , filters ) ) ; // Compare across all filters
2016-07-23 08:04:55 +00:00
}
2016-12-23 21:37:53 +00:00
if ( Menu_SearchClones . Checked )
2017-06-18 01:37:19 +00:00
res = res . GroupBy ( Hash ) . Where ( group = > group . Count ( ) > 1 ) . SelectMany ( z = > z ) ;
2016-12-23 21:37:53 +00:00
2017-05-30 02:18:18 +00:00
return res ;
}
2017-09-30 05:58:25 +00:00
private static bool IsPKMFiltered ( PKM pkm , IEnumerable < BatchEditor . StringInstruction > filters )
{
foreach ( var cmd in filters )
{
if ( cmd . PropertyName = = nameof ( PKM . Identifier ) + "Contains" )
2017-10-20 15:47:31 +00:00
{
bool result = pkm . Identifier . Contains ( cmd . PropertyValue ) ;
if ( result ! = cmd . Evaluator )
return false ;
continue ;
}
2017-09-30 05:58:25 +00:00
if ( ! pkm . GetType ( ) . HasPropertyAll ( cmd . PropertyName ) )
return false ;
try { if ( pkm . GetType ( ) . IsValueEqual ( pkm , cmd . PropertyName , cmd . PropertyValue ) = = cmd . Evaluator ) continue ; }
catch { Debug . WriteLine ( $"Unable to compare {cmd.PropertyName} to {cmd.PropertyValue}." ) ; }
return false ;
}
return true ;
}
2017-08-25 01:49:09 +00:00
private static IEnumerable < PKM > FilterByLVL ( IEnumerable < PKM > res , int option , string lvl )
{
if ( string . IsNullOrWhiteSpace ( lvl ) )
return res ;
if ( ! int . TryParse ( lvl , out int level ) )
return res ;
if ( level > 100 )
return res ;
switch ( option )
{
case 0 : break ; // Any (Do nothing)
2018-01-27 21:24:16 +00:00
case 3 : // <=
2017-08-25 01:49:09 +00:00
return res . Where ( pk = > pk . Stat_Level < = level ) ;
case 2 : // ==
return res . Where ( pk = > pk . Stat_Level = = level ) ;
2018-01-27 21:24:16 +00:00
case 1 : // >=
2017-08-25 01:49:09 +00:00
return res . Where ( pk = > pk . Stat_Level > = level ) ;
}
return res ;
}
private static IEnumerable < PKM > FilterByEVs ( IEnumerable < PKM > res , int option )
{
switch ( option )
{
case 0 : break ; // Any (Do nothing)
case 1 : // None (0)
return res . Where ( pk = > pk . EVs . Sum ( ) = = 0 ) ;
case 2 : // Some (127-0)
return res . Where ( pk = > pk . EVs . Sum ( ) < 128 ) ;
case 3 : // Half (128-507)
return res . Where ( pk = > pk . EVs . Sum ( ) > = 128 & & pk . EVs . Sum ( ) < 508 ) ;
case 4 : // Full (508+)
return res . Where ( pk = > pk . EVs . Sum ( ) > = 508 ) ;
}
return res ;
}
private static IEnumerable < PKM > FilterByIVs ( IEnumerable < PKM > res , int option )
{
switch ( option )
{
case 0 : break ; // Do nothing
case 1 : // <= 90
return res . Where ( pk = > pk . IVs . Sum ( ) < = 90 ) ;
case 2 : // 91-120
return res . Where ( pk = > pk . IVs . Sum ( ) > 90 & & pk . IVs . Sum ( ) < = 120 ) ;
case 3 : // 121-150
return res . Where ( pk = > pk . IVs . Sum ( ) > 120 & & pk . IVs . Sum ( ) < = 150 ) ;
case 4 : // 151-179
return res . Where ( pk = > pk . IVs . Sum ( ) > 150 & & pk . IVs . Sum ( ) < 180 ) ;
case 5 : // 180+
return res . Where ( pk = > pk . IVs . Sum ( ) > = 180 ) ;
case 6 : // == 186
return res . Where ( pk = > pk . IVs . Sum ( ) = = 186 ) ;
}
return res ;
}
2017-05-30 02:18:18 +00:00
private async void B_Search_Click ( object sender , EventArgs e )
{
B_Search . Enabled = false ;
var search = SearchDatabase ( ) ;
2017-09-20 23:46:40 +00:00
bool legalSearch = Menu_SearchLegal . Checked ^ Menu_SearchIllegal . Checked ;
if ( legalSearch & & WinFormsUtil . Prompt ( MessageBoxButtons . YesNo , "Check wordfilter legality?" ) = = DialogResult . No )
Legal . CheckWordFilter = false ;
2017-05-30 02:18:18 +00:00
var results = await Task . Run ( ( ) = > search . ToArray ( ) ) ;
2017-09-20 23:46:40 +00:00
Legal . CheckWordFilter = true ;
2015-10-08 03:19:34 +00:00
if ( results . Length = = 0 )
2015-11-14 02:31:01 +00:00
{
if ( ! Menu_SearchBoxes . Checked & & ! Menu_SearchDatabase . Checked )
2017-01-08 07:54:09 +00:00
WinFormsUtil . Alert ( "No data source to search!" , "No results found!" ) ;
2015-11-14 02:31:01 +00:00
else
2017-01-08 07:54:09 +00:00
WinFormsUtil . Alert ( "No results found!" ) ;
2015-11-14 02:31:01 +00:00
}
2017-06-18 01:37:19 +00:00
SetResults ( new List < PKM > ( results ) ) ; // updates Count Label as well.
2015-10-08 03:19:34 +00:00
System . Media . SystemSounds . Asterisk . Play ( ) ;
2017-05-30 02:18:18 +00:00
B_Search . Enabled = true ;
2015-10-08 03:19:34 +00:00
}
2017-06-18 01:37:19 +00:00
private void UpdateScroll ( object sender , ScrollEventArgs e )
2015-10-08 03:19:34 +00:00
{
if ( e . OldValue ! = e . NewValue )
FillPKXBoxes ( e . NewValue ) ;
}
2017-06-18 01:37:19 +00:00
private void SetResults ( List < PKM > res )
2015-10-10 17:28:24 +00:00
{
2016-06-20 04:22:43 +00:00
Results = new List < PKM > ( res ) ;
2015-10-08 03:19:34 +00:00
2015-10-10 17:28:24 +00:00
SCR_Box . Maximum = ( int ) Math . Ceiling ( ( decimal ) Results . Count / RES_MIN ) ;
if ( SCR_Box . Maximum > 0 ) SCR_Box . Maximum - = 1 ;
SCR_Box . Value = 0 ;
FillPKXBoxes ( 0 ) ;
2016-02-01 07:15:54 +00:00
L_Count . Text = string . Format ( Counter , Results . Count ) ;
2017-09-05 05:22:02 +00:00
B_Search . Enabled = true ;
2015-10-10 17:28:24 +00:00
}
2015-10-08 03:19:34 +00:00
private void FillPKXBoxes ( int start )
{
if ( Results = = null )
2016-09-04 18:02:27 +00:00
{
2015-10-08 03:19:34 +00:00
for ( int i = 0 ; i < RES_MAX ; i + + )
PKXBOXES [ i ] . Image = null ;
2016-09-04 18:02:27 +00:00
return ;
}
2017-04-21 03:52:08 +00:00
int begin = start * RES_MIN ;
int end = Math . Min ( RES_MAX , Results . Count - start * RES_MIN ) ;
for ( int i = 0 ; i < end ; i + + )
PKXBOXES [ i ] . Image = Results [ i + begin ] . Sprite ( ) ;
for ( int i = end ; i < RES_MAX ; i + + )
2015-10-08 03:19:34 +00:00
PKXBOXES [ i ] . Image = null ;
for ( int i = 0 ; i < RES_MAX ; i + + )
2017-05-12 04:34:18 +00:00
PKXBOXES [ i ] . BackgroundImage = Properties . Resources . slotTrans ;
2015-10-08 03:19:34 +00:00
if ( slotSelected ! = - 1 & & slotSelected > = RES_MIN * start & & slotSelected < RES_MIN * start + RES_MAX )
2017-05-12 04:34:18 +00:00
PKXBOXES [ slotSelected - start * RES_MIN ] . BackgroundImage = slotColor ? ? Properties . Resources . slotView ;
2015-10-08 03:19:34 +00:00
}
// Misc Update Methods
2017-06-18 01:37:19 +00:00
private void ToggleESV ( object sender , EventArgs e )
2015-10-08 03:19:34 +00:00
{
L_ESV . Visible = MT_ESV . Visible = CHK_IsEgg . CheckState = = CheckState . Checked ;
}
2017-06-18 01:37:19 +00:00
private void ChangeLevel ( object sender , EventArgs e )
2015-10-08 03:19:34 +00:00
{
if ( CB_Level . SelectedIndex = = 0 )
TB_Level . Text = "" ;
}
2017-06-18 01:37:19 +00:00
private void ChangeGame ( object sender , EventArgs e )
2015-10-10 17:18:55 +00:00
{
if ( CB_GameOrigin . SelectedIndex ! = 0 )
CB_Generation . SelectedIndex = 0 ;
}
2017-06-18 01:37:19 +00:00
private void ChangeGeneration ( object sender , EventArgs e )
2015-10-10 17:18:55 +00:00
{
if ( CB_Generation . SelectedIndex ! = 0 )
CB_GameOrigin . SelectedIndex = 0 ;
}
2015-10-08 03:19:34 +00:00
2016-07-23 08:04:55 +00:00
private void Menu_SearchAdvanced_Click ( object sender , EventArgs e )
{
if ( ! Menu_SearchAdvanced . Checked )
{ Size = MinimumSize ; RTB_Instructions . Clear ( ) ; }
else Size = MaximumSize ;
}
2015-11-14 03:04:42 +00:00
private void Menu_Exit_Click ( object sender , EventArgs e )
{
Close ( ) ;
}
2016-03-19 02:33:09 +00:00
protected override void OnMouseWheel ( MouseEventArgs e )
{
if ( ! PAN_Box . RectangleToScreen ( PAN_Box . ClientRectangle ) . Contains ( MousePosition ) )
return ;
int oldval = SCR_Box . Value ;
int newval = oldval + ( e . Delta < 0 ? 1 : - 1 ) ;
if ( newval > = SCR_Box . Minimum & & SCR_Box . Maximum > = newval )
FillPKXBoxes ( SCR_Box . Value = newval ) ;
}
2016-07-10 17:33:01 +00:00
2017-06-18 01:37:19 +00:00
private void ChangeFormatFilter ( object sender , EventArgs e )
2016-07-10 17:33:01 +00:00
{
if ( CB_FormatComparator . SelectedIndex = = 0 )
{
CB_Format . Visible = false ; // !any
CB_Format . SelectedIndex = 0 ;
}
else
{
CB_Format . Visible = true ;
2017-05-23 04:55:05 +00:00
int index = MAXFORMAT - SAV . Generation + 1 ;
2016-09-05 01:17:13 +00:00
CB_Format . SelectedIndex = index < CB_Format . Items . Count ? index : 0 ; // SAV generation (offset by 1 for "Any")
2016-07-10 17:33:01 +00:00
}
}
2016-12-23 22:12:58 +00:00
private void Menu_DeleteClones_Click ( object sender , EventArgs e )
{
2017-01-08 07:54:09 +00:00
var dr = WinFormsUtil . Prompt ( MessageBoxButtons . YesNo ,
2016-12-23 22:12:58 +00:00
"Deleting clones from database is not reversible." + Environment . NewLine +
"If a PKM is deemed a clone, only the newest file (date modified) will be kept." , "Continue?" ) ;
if ( dr ! = DialogResult . Yes )
return ;
var deleted = 0 ;
2017-01-03 06:17:47 +00:00
var db = RawDB . Where ( pk = > pk . Identifier . StartsWith ( DatabasePath + Path . DirectorySeparatorChar , StringComparison . Ordinal ) )
2016-12-23 22:12:58 +00:00
. OrderByDescending ( file = > new FileInfo ( file . Identifier ) . LastWriteTime ) ;
2017-06-18 01:37:19 +00:00
var clones = db . GroupBy ( Hash ) . Where ( group = > group . Count ( ) > 1 ) . SelectMany ( z = > z . Skip ( 1 ) ) ;
2017-04-27 16:15:16 +00:00
foreach ( var pk in clones )
2016-12-23 22:12:58 +00:00
{
try { File . Delete ( pk . Identifier ) ; + + deleted ; }
2017-01-08 07:54:09 +00:00
catch { WinFormsUtil . Error ( "Unable to delete clone:" + Environment . NewLine + pk . Identifier ) ; }
2016-12-23 22:12:58 +00:00
}
if ( deleted = = 0 )
2017-01-08 07:54:09 +00:00
{ WinFormsUtil . Alert ( "No clones detected or deleted." ) ; return ; }
2016-12-23 22:12:58 +00:00
2017-01-08 07:54:09 +00:00
WinFormsUtil . Alert ( $"{deleted} files deleted." , "The form will now close." ) ;
2016-12-23 22:12:58 +00:00
Close ( ) ;
}
2015-10-06 01:51:52 +00:00
}
}