// many thanks to https://www.winprog.org/tutorial from where I got a lot of // code for this #include #include #include #include #include #include #include "filesystem.hpp" #include "functions.hpp" #include "resource.h" #include "tv_rename.hpp" constexpr std::array< const wchar_t *, 46 > languages{ L"en", L"English", L"sv", L"Svenska", L"no", L"Norsk", L"da", L"Dansk", L"fi", L"Suomeksi", L"nl", L"Nederlands", L"de", L"Deutsch", L"it", L"Italiano", L"es", L"Español", L"fr", L"Français", L"pl", L"Polski", L"hu", L"Magyar", L"el", L"Greek", L"tr", L"Turkish", L"ru", L"Russian", L"he", L"Hebrew", L"ja", L"Japanese", L"pt", L"Portuguese", L"zh", L"Chinese", L"cs", L"Czech", L"sl", L"Slovenian", L"hr", L"Croatian", L"ko", L"Korea" }; std::vector< int > options; std::vector< int > checkboxes; std::vector< int > checked; Curl c; wchar_t lang_code[3] = L"en"; std::wstring default_pattern = L"%filename - %epname"; std::map< int, std::set< string > > files; std::vector< std::pair< string, string > > possible_shows; std::vector< std::pair< string, std::pair< string, string > > > *current_renamed_files{ nullptr }; BOOL CALLBACK HelpBox( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDOK: EndDialog( hwnd, 0 ); default: break; } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; default: return FALSE; } return TRUE; } BOOL CALLBACK SeasonsBox( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_INITDIALOG: { checked.clear(); checkboxes.clear(); int left{ 15 }, top{ 30 }; for ( int i = 0; i < options.size(); i++ ) { if ( checkboxes.empty() ) { checkboxes.push_back( 2000 ); } else { checkboxes.push_back( checkboxes.back() + 1 ); } auto hCheckBox = CreateWindowEx( 0, L"Button", std::to_wstring( options[i] ).c_str(), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, left, top, 60, 20, hwnd, ( HMENU )checkboxes.back(), GetModuleHandle( NULL ), NULL ); if ( hCheckBox == NULL ) { MessageBox( hwnd, L"Could not create checkbox", L"Error", MB_OK | MB_ICONERROR ); return TRUE; } auto hfDefault = GetStockObject( DEFAULT_GUI_FONT ); SendMessage( hCheckBox, WM_SETFONT, ( WPARAM )hfDefault, MAKELPARAM( FALSE, 0 ) ); if ( left == 195 ) { left = 15; top += 20; } else { left += 60; } } } return TRUE; case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDOK: for ( int i = 0; i < checkboxes.size(); i++ ) { if ( SendDlgItemMessage( hwnd, checkboxes[i], BM_GETCHECK, 0, 0 ) ) checked.push_back( options[i] ); } EndDialog( hwnd, 0 ); break; case IDALL: for ( auto &x : checkboxes ) { SendDlgItemMessage( hwnd, x, BM_SETCHECK, BST_CHECKED, 0 ); } break; case IDNONE: for ( auto &x : checkboxes ) { SendDlgItemMessage( hwnd, x, BM_SETCHECK, BST_UNCHECKED, 0 ); } break; default: break; } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; default: return FALSE; } return TRUE; } // stolen from // https://www.codeproject.com/Articles/2604/Browse-Folder-dialog-search-folder-and-all-sub-fol std::wstring getDir() { wchar_t path[MAX_PATH]; BROWSEINFO bi{}; bi.lpszTitle = L"Choose a folder"; LPITEMIDLIST pidl = SHBrowseForFolder( &bi ); if ( pidl != 0 ) { SHGetPathFromIDList( pidl, path ); IMalloc *imalloc = 0; if ( SUCCEEDED( SHGetMalloc( &imalloc ) ) ) { imalloc->Free( pidl ); imalloc->Release(); } } else { path[0] = '\0'; } return path; } void renameFiles( const std::vector< std::pair< string, std::pair< string, string > > > &renamed ) { for ( auto renamed_it = renamed.begin(); renamed_it != renamed.end(); ++renamed_it ) { FSLib::rename( renamed_it->first + L"\\" + renamed_it->second.first, renamed_it->first + L"\\" + renamed_it->second.second ); } } BOOL CALLBACK PreviewBox( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_INITDIALOG: { std::wstring text{}; for ( auto renamed_it = current_renamed_files->begin(); renamed_it != current_renamed_files->end(); ++renamed_it ) { text += renamed_it->second.first + L" --> " + renamed_it->second.second + L"\r\n"; } SetDlgItemText( hwnd, IDTEXT, text.c_str() ); } return TRUE; case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDYES: { renameFiles( *current_renamed_files ); EndDialog( hwnd, IDYES ); } break; case IDNO: EndDialog( hwnd, IDNO ); default: break; } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; default: return FALSE; } return TRUE; } void finishedSelection( HWND hwnd ) { auto index = SendDlgItemMessage( hwnd, IDSHOWS, CB_GETCURSEL, 0, 0 ); auto url = possible_shows[index].second; auto show = possible_shows[index].first; wchar_t input_pattern[100]; GetDlgItemText( hwnd, IDPATTERN, input_pattern, 100 ); if ( input_pattern != default_pattern ) { std::wofstream file( userHome() + L"\\tv_rename\\pattern" ); if ( file ) { file << input_pattern; } } for ( auto &x : checked ) { auto renamed_files = getRenamedFiles( show, x, L"https://www.thetvdb.com" + url, lang_code, ( input_pattern[0] == '\0' ? default_pattern : input_pattern ), false, c, files[x] ); if ( renamed_files.empty() ) continue; if ( SendDlgItemMessage( hwnd, IDTRUST, BM_GETCHECK, 0, 0 ) ) { renameFiles( renamed_files ); continue; } current_renamed_files = &renamed_files; DialogBox( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDD_PREVIEW ), hwnd, PreviewBox ); } if ( SendDlgItemMessage( hwnd, IDTRUST, BM_GETCHECK, 0, 0 ) ) { MessageBox( hwnd, L"Finished renaming files", L"Info", MB_OK | MB_ICONINFORMATION ); } } void getNames( HWND hwnd ) { wchar_t path[MAX_PATH]; GetDlgItemText( hwnd, IDDIR, path, MAX_PATH ); if ( wcslen( path ) == 0 ) { MessageBox( hwnd, L"Folder field is empty", L"Error", MB_OK | MB_ICONERROR ); return; } if ( !FSLib::isDirectory( path ) ) { MessageBox( hwnd, L"Folder doesn't exist", L"Error", MB_OK | MB_ICONERROR ); return; } checked.clear(); checkboxes.clear(); options.clear(); files.clear(); iterateFS( files, path ); for ( auto &x : files ) { options.push_back( x.first ); } DialogBox( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDD_SEASONS ), hwnd, SeasonsBox ); finishedSelection( hwnd ); } void process( HWND hwnd ) { wchar_t show[100]; GetDlgItemText( hwnd, IDSHOWIN, show, 100 ); if ( wcslen( show ) == 0 ) { MessageBox( hwnd, L"Show field is empty", L"Error", MB_OK | MB_ICONERROR ); return; } wchar_t language[20]; GetDlgItemText( hwnd, IDLANG, language, 20 ); for ( int i = 1; i < languages.size(); i += 2 ) { if ( !wcscmp( languages[i], language ) ) { wcscpy_s( lang_code, languages[i - 1] ); break; } } possible_shows = getPossibleShows( show, lang_code, c ); if ( possible_shows.size() == 0 ) { MessageBox( hwnd, L"No results found for given show name", L"Error", MB_OK | MB_ICONERROR ); return; } ShowWindow( GetDlgItem( hwnd, ID_STATIC6 ), SW_SHOW ); ShowWindow( GetDlgItem( hwnd, IDSHOWS ), SW_SHOW ); ShowWindow( GetDlgItem( hwnd, IDSEASONS ), SW_SHOW ); SendDlgItemMessage( hwnd, IDSHOWS, CB_RESETCONTENT, 0, 0 ); for ( int i = 0; i < possible_shows.size(); i++ ) { SendDlgItemMessage( hwnd, IDSHOWS, CB_ADDSTRING, 0, ( LPARAM )possible_shows[i].first.c_str() ); } SendDlgItemMessage( hwnd, IDSHOWS, CB_SETCURSEL, 0, 0 ); } void readDefaultPattern( const string &base_dir ) { std::wifstream file( base_dir + L"\\pattern" ); if ( file ) { std::getline( file, default_pattern ); } } BOOL CALLBACK MainBox( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_INITDIALOG: { for ( int i = 1; i < languages.size(); i += 2 ) { SendDlgItemMessage( hwnd, IDLANG, CB_ADDSTRING, 0, ( LPARAM )languages[i] ); } SendDlgItemMessage( hwnd, IDLANG, CB_SETCURSEL, 5, 0 ); auto appdata = userHome() + L"\\tv_rename"; if ( !FSLib::isDirectory( appdata ) ) { if ( CreateDirectory( appdata.c_str(), NULL ) ) { readDefaultPattern( appdata ); } } else { readDefaultPattern( appdata ); } SetDlgItemText( hwnd, IDPATTERN, default_pattern.c_str() ); } return TRUE; case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDPROCESS: { process( hwnd ); } break; case IDEND: EndDialog( hwnd, IDOK_MAIN ); break; case IDSEASONS: getNames( hwnd ); break; case IDDIRB: SetDlgItemText( hwnd, IDDIR, getDir().c_str() ); break; case IDHELP: DialogBox( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDD_HELP ), hwnd, HelpBox ); break; default: break; } break; case WM_CLOSE: EndDialog( hwnd, 0 ); break; default: return FALSE; } return TRUE; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { return DialogBox( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDD_MAIN ), NULL, MainBox ); }