432 lines
14 KiB
C++
432 lines
14 KiB
C++
|
#include "mainwindow.hpp"
|
||
|
#include "../filesystem.hpp"
|
||
|
#include "../functions.hpp"
|
||
|
#include "../tv_rename.hpp"
|
||
|
#include "databasewindow.hpp"
|
||
|
#include "gui_functions.hpp"
|
||
|
#include "patternwindow.hpp"
|
||
|
#include "progresswindow.hpp"
|
||
|
#include "searchwindow.hpp"
|
||
|
#include "seasonwindow.hpp"
|
||
|
|
||
|
#include <fstream>
|
||
|
#include <thread>
|
||
|
|
||
|
#define API_KEY "42B66F5E-C6BF-423F-ADF9-CC97163472F6"
|
||
|
|
||
|
#define ID_SHOW_STATIC 0x0001
|
||
|
#define ID_LANGUAGE_STATIC 0x0002
|
||
|
#define ID_DIR_STATIC 0x0003
|
||
|
#define ID_PATTERN_STATIC 0x0004
|
||
|
#define ID_POSSIBLE_STATIC 0x0005
|
||
|
|
||
|
#define ID_SHOW_EDIT 0x1000
|
||
|
#define ID_LANGUAGE_COMBO 0x1001
|
||
|
#define ID_DIR_EDIT 0x1002
|
||
|
#define ID_DIR_BUTTON 0x1003
|
||
|
#define ID_PATTERN_EDIT 0x1004
|
||
|
#define ID_PATTERN_BUTTON 0x1005
|
||
|
#define ID_PROCESS_BUTTON 0x1006
|
||
|
#define ID_RENAME_CHECKBOX 0x1007
|
||
|
#define ID_SHOW_COMBO 0x1008
|
||
|
#define ID_RENAME_BUTTON 0x1009
|
||
|
#define ID_QUIT_BUTTON 0x100a
|
||
|
#define ID_DVD_CHECKBOX 0x100b
|
||
|
#define ID_DB_ADD_BUTTON 0x100c
|
||
|
|
||
|
#define MENU_FILE_EXIT 0x2000
|
||
|
#define MENU_DAT_UPDATE 0x2001
|
||
|
#define MENU_DAT_REFRESH 0x2002
|
||
|
#define MENU_DAT_CLEAN 0x2003
|
||
|
#define MENU_DAT_MANAGE 0x2004
|
||
|
#define MENU_DAT_PATTERN 0x2005
|
||
|
|
||
|
MainWindow *MainWindow::mw = nullptr;
|
||
|
|
||
|
MainWindow::MainWindow( HINSTANCE hInstance, int nCmdShow )
|
||
|
: hInst( hInstance ) {
|
||
|
window = CreateWindowW( L"MainWindow", L"TV Rename",
|
||
|
WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME | WS_VISIBLE,
|
||
|
CW_USEDEFAULT, CW_USEDEFAULT, window_width,
|
||
|
window_height, NULL, NULL, hInst, NULL );
|
||
|
ShowWindow( window, nCmdShow );
|
||
|
hFont = ( HFONT )GetStockObject( DEFAULT_GUI_FONT );
|
||
|
|
||
|
authenticate( API_KEY );
|
||
|
languages = getLangs();
|
||
|
|
||
|
createLabel( L"Show:", 5, 5, 30, 15, ID_SHOW_STATIC, window, hFont );
|
||
|
createLabel( L"Language:", 170, 5, 55, 15, ID_LANGUAGE_STATIC, window,
|
||
|
hFont );
|
||
|
createLabel( L"Directory:", 5, 45, 65, 15, ID_DIR_STATIC, window, hFont );
|
||
|
createLabel( L"Pattern:", 5, 85, 55, 15, ID_PATTERN_STATIC, window, hFont );
|
||
|
possible_label = createLabel( L"Possible shows:", 5, 190, 100, 15,
|
||
|
ID_POSSIBLE_STATIC, window, hFont );
|
||
|
show_input = createEditBox( 5, 20, 160, 25, ID_SHOW_EDIT, window, hFont );
|
||
|
language_input =
|
||
|
createCombo( 170, 20, 160, 250, ID_LANGUAGE_COMBO, window, hFont );
|
||
|
for ( auto &x : languages ) {
|
||
|
addItemToCombo( language_input, x.second.c_str() );
|
||
|
}
|
||
|
SendMessage( language_input, CB_SETCURSEL, langPos( L"en" ), NULL );
|
||
|
|
||
|
dir_input = createEditBox( 5, 60, 160, 25, ID_DIR_EDIT, window, hFont );
|
||
|
createButton( L"Choose directory", 170, 60, 120, 25, ID_DIR_BUTTON, window,
|
||
|
hFont );
|
||
|
pattern_input =
|
||
|
createEditBox( 5, 100, 160, 25, ID_PATTERN_EDIT, window, hFont );
|
||
|
createButton( L"Pattern help", 170, 100, 100, 25, ID_PATTERN_BUTTON, window,
|
||
|
hFont );
|
||
|
createButton( L"Process", 5, 140, 80, 25, ID_PROCESS_BUTTON, window,
|
||
|
hFont );
|
||
|
trust_input = createCheckbox( L"Don't ask for rename confirmation", 90, 146,
|
||
|
180, 12, ID_RENAME_CHECKBOX, window, hFont );
|
||
|
dvd_input = createCheckbox( L"Use DVD ordering", 5, 170, 180, 12,
|
||
|
ID_DVD_CHECKBOX, window, hFont );
|
||
|
possible_input = createCombo( 5, 205, 160, window_height - 220,
|
||
|
ID_SHOW_COMBO, window, hFont );
|
||
|
rename_button = createButton( L"Rename", 5, 230, 80, 25, ID_RENAME_BUTTON,
|
||
|
window, hFont );
|
||
|
db_add_button = createButton( L"Add to database", 90, 230, 100, 25,
|
||
|
ID_DB_ADD_BUTTON, window, hFont );
|
||
|
createButton( L"Quit", window_width - 100, window_height - 88, 80, 25,
|
||
|
ID_QUIT_BUTTON, window, hFont );
|
||
|
|
||
|
// MENUS
|
||
|
HMENU hMenuBar = CreateMenu();
|
||
|
HMENU hMenuFile = CreateMenu();
|
||
|
HMENU hMenuDatabase = CreateMenu();
|
||
|
|
||
|
AppendMenuW( hMenuFile, MF_STRING, MENU_FILE_EXIT, L"&Exit" );
|
||
|
AppendMenuW( hMenuDatabase, MF_STRING, MENU_DAT_UPDATE,
|
||
|
L"&Update database" );
|
||
|
AppendMenuW( hMenuDatabase, MF_STRING, MENU_DAT_REFRESH,
|
||
|
L"&Refresh database" );
|
||
|
AppendMenuW( hMenuDatabase, MF_STRING, MENU_DAT_CLEAN, L"&Clean database" );
|
||
|
AppendMenuW( hMenuDatabase, MF_STRING, MENU_DAT_MANAGE,
|
||
|
L"&Manage database" );
|
||
|
AppendMenuW( hMenuDatabase, MF_STRING, MENU_DAT_PATTERN,
|
||
|
L"Change &pattern" );
|
||
|
|
||
|
AppendMenuW( hMenuBar, MF_POPUP, ( UINT_PTR )hMenuFile, L"&File" );
|
||
|
AppendMenuW( hMenuBar, MF_POPUP, ( UINT_PTR )hMenuDatabase, L"&Database" );
|
||
|
SetMenu( window, hMenuBar );
|
||
|
|
||
|
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
|
||
|
icex.dwICC = ICC_LISTVIEW_CLASSES;
|
||
|
InitCommonControlsEx( &icex );
|
||
|
|
||
|
auto appdata = userHome() + L"\\tv_rename";
|
||
|
if ( !FSLib::isDirectory( appdata ) ) {
|
||
|
// create the directory so pattern can be stored when changed
|
||
|
CreateDirectory( appdata.c_str(), NULL );
|
||
|
} else {
|
||
|
readDefaultPattern( appdata );
|
||
|
}
|
||
|
|
||
|
SendMessage( pattern_input, WM_SETTEXT, NULL,
|
||
|
( LPARAM )default_pattern.c_str() );
|
||
|
ShowWindow( possible_label, SW_HIDE );
|
||
|
ShowWindow( possible_input, SW_HIDE );
|
||
|
ShowWindow( rename_button, SW_HIDE );
|
||
|
ShowWindow( db_add_button, SW_HIDE );
|
||
|
|
||
|
UpdateWindow( window );
|
||
|
}
|
||
|
|
||
|
LRESULT CALLBACK MainWindow::messageHandler( HWND hwnd, UINT umsg,
|
||
|
WPARAM wParam, LPARAM lParam ) {
|
||
|
switch ( umsg ) {
|
||
|
case WM_CREATE:
|
||
|
centerWindow( hwnd );
|
||
|
break;
|
||
|
case WM_COMMAND:
|
||
|
switch ( LOWORD( wParam ) ) {
|
||
|
case ID_QUIT_BUTTON:
|
||
|
case MENU_FILE_EXIT:
|
||
|
SendMessage( hwnd, WM_CLOSE, 0, 0 );
|
||
|
break;
|
||
|
case ID_PROCESS_BUTTON:
|
||
|
mw->process();
|
||
|
break;
|
||
|
case ID_DIR_BUTTON:
|
||
|
SendMessage( mw->dir_input, WM_SETTEXT, NULL,
|
||
|
( LPARAM )getDir().c_str() );
|
||
|
break;
|
||
|
case MENU_DAT_UPDATE:
|
||
|
dbUpdate();
|
||
|
break;
|
||
|
case MENU_DAT_REFRESH:
|
||
|
dbRefresh();
|
||
|
break;
|
||
|
case MENU_DAT_CLEAN:
|
||
|
dbClean();
|
||
|
break;
|
||
|
case MENU_DAT_MANAGE:
|
||
|
dbManage();
|
||
|
break;
|
||
|
case MENU_DAT_PATTERN:
|
||
|
dbPattern();
|
||
|
break;
|
||
|
case ID_PATTERN_BUTTON:
|
||
|
patternHelp();
|
||
|
break;
|
||
|
case ID_RENAME_BUTTON:
|
||
|
mw->rename();
|
||
|
break;
|
||
|
case ID_DB_ADD_BUTTON:
|
||
|
mw->dbAdd();
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case WM_DESTROY:
|
||
|
PostQuitMessage( 0 );
|
||
|
break;
|
||
|
}
|
||
|
return DefWindowProcW( hwnd, umsg, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
void MainWindow::mainLoop() {
|
||
|
MSG msg;
|
||
|
while ( GetMessage( &msg, NULL, 0, 0 ) ) {
|
||
|
if ( !IsDialogMessage( window, &msg ) ) {
|
||
|
TranslateMessage( &msg );
|
||
|
mw = this;
|
||
|
DispatchMessage( &msg );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int MainWindow::langPos( const std::wstring &lang ) {
|
||
|
for ( unsigned long long i = 0; i < languages.size(); i++ ) {
|
||
|
if ( languages[i].first == lang )
|
||
|
return i;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void MainWindow::readDefaultPattern( const std::wstring &base_dir ) {
|
||
|
std::wifstream file( base_dir + L"\\pattern" );
|
||
|
if ( file ) {
|
||
|
std::getline( file, default_pattern );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MainWindow::process() {
|
||
|
wchar_t show[256];
|
||
|
SendMessage( show_input, WM_GETTEXT, ( WPARAM )255, ( LPARAM )show );
|
||
|
if ( wcslen( show ) == 0 ) {
|
||
|
MessageBox( window, L"Show field is empty", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto index = SendMessage( language_input, CB_GETCURSEL, NULL, NULL );
|
||
|
if ( index == CB_ERR ) {
|
||
|
MessageBox( window, L"No show selected", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
auto lang_code = languages[index].first;
|
||
|
|
||
|
possible_shows = searchShow( show, lang_code );
|
||
|
if ( possible_shows.size() == 0 ) {
|
||
|
MessageBox( window, L"No results found for given show name", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SendMessage( possible_input, CB_RESETCONTENT, NULL, NULL );
|
||
|
for ( const auto &x : possible_shows ) {
|
||
|
SendMessage( possible_input, CB_ADDSTRING, NULL,
|
||
|
( LPARAM )x.first.c_str() );
|
||
|
}
|
||
|
SendMessage( possible_input, CB_SETCURSEL, 0, 0 );
|
||
|
|
||
|
ShowWindow( mw->possible_label, SW_SHOW );
|
||
|
ShowWindow( mw->possible_input, SW_SHOW );
|
||
|
ShowWindow( mw->rename_button, SW_SHOW );
|
||
|
ShowWindow( mw->db_add_button, SW_SHOW );
|
||
|
}
|
||
|
|
||
|
void MainWindow::rename() {
|
||
|
wchar_t path[MAX_PATH];
|
||
|
SendMessage( dir_input, WM_GETTEXT, ( WPARAM )MAX_PATH - 1,
|
||
|
( LPARAM )path );
|
||
|
if ( wcslen( path ) == 0 ) {
|
||
|
MessageBox( window, L"Directory field is empty", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
if ( !FSLib::isDirectory( path ) ) {
|
||
|
MessageBox( window, L"Directory doesn't exist", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
selected.clear();
|
||
|
files.clear();
|
||
|
std::vector< int > options{};
|
||
|
|
||
|
iterateFS( files, path );
|
||
|
for ( auto &x : files ) {
|
||
|
options.push_back( x.first );
|
||
|
}
|
||
|
|
||
|
SeasonWindow sw( hInst, options, selected, window );
|
||
|
sw.mainLoop();
|
||
|
|
||
|
auto index = SendMessage( possible_input, CB_GETCURSEL, NULL, NULL );
|
||
|
if ( index == CB_ERR ) {
|
||
|
MessageBox( window, L"No show selected", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
auto show = possible_shows[index].first;
|
||
|
auto show_id = possible_shows[index].second;
|
||
|
|
||
|
index = SendMessage( language_input, CB_GETCURSEL, NULL, NULL );
|
||
|
if ( index == CB_ERR ) {
|
||
|
MessageBox( window, L"No show selected", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto lang = languages[index].first;
|
||
|
bool dvd = SendMessage( dvd_input, BM_GETCHECK, NULL, NULL ) == BST_CHECKED;
|
||
|
bool trust =
|
||
|
SendMessage( trust_input, BM_GETCHECK, NULL, NULL ) == BST_CHECKED;
|
||
|
|
||
|
wchar_t input_pattern_wchar[MAX_PATH];
|
||
|
SendMessage( pattern_input, WM_GETTEXT, ( WPARAM )MAX_PATH,
|
||
|
( LPARAM )input_pattern_wchar );
|
||
|
if ( wcscmp( input_pattern_wchar, default_pattern.c_str() ) ) {
|
||
|
std::wofstream file( userHome() + L"\\tv_rename\\pattern" );
|
||
|
if ( file ) {
|
||
|
file << input_pattern_wchar;
|
||
|
}
|
||
|
}
|
||
|
std::wstring input_pattern = input_pattern_wchar;
|
||
|
|
||
|
for ( auto &season : selected ) {
|
||
|
auto renamed_files = getRenamedFiles(
|
||
|
show, season, show_id, lang,
|
||
|
( input_pattern.empty() ? default_pattern : input_pattern ), false,
|
||
|
files[season], dvd );
|
||
|
if ( renamed_files.empty() ) {
|
||
|
continue;
|
||
|
}
|
||
|
if ( trust ) {
|
||
|
renameFiles( renamed_files );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
std::wstring message_text;
|
||
|
for ( auto &file : renamed_files ) {
|
||
|
message_text += std::get< 2 >( file ) + L" --> " +
|
||
|
std::get< 3 >( file ) + L"\n";
|
||
|
}
|
||
|
|
||
|
auto res = MessageBox( window, message_text.c_str(), L"Is this OK?",
|
||
|
MB_OKCANCEL );
|
||
|
if ( res == IDOK )
|
||
|
renameFiles( renamed_files );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbAdd() {
|
||
|
wchar_t path[MAX_PATH];
|
||
|
SendMessage( dir_input, WM_GETTEXT, ( WPARAM )MAX_PATH - 1,
|
||
|
( LPARAM )path );
|
||
|
if ( wcslen( path ) == 0 ) {
|
||
|
MessageBox( window, L"Directory field is empty", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
if ( !FSLib::isDirectory( path ) ) {
|
||
|
MessageBox( window, L"Directory doesn't exist", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto index = SendMessage( possible_input, CB_GETCURSEL, NULL, NULL );
|
||
|
if ( index == CB_ERR ) {
|
||
|
MessageBox( window, L"No show selected", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto show = possible_shows[index].first;
|
||
|
auto show_id = possible_shows[index].second;
|
||
|
|
||
|
index = SendMessage( language_input, CB_GETCURSEL, NULL, NULL );
|
||
|
if ( index == CB_ERR ) {
|
||
|
MessageBox( window, L"No language selected", L"Error",
|
||
|
MB_OK | MB_ICONERROR );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto lang = languages[index].first;
|
||
|
bool dvd = SendMessage( dvd_input, BM_GETCHECK, NULL, NULL ) == BST_CHECKED;
|
||
|
|
||
|
ProgressWindow pw( hInst, window );
|
||
|
std::thread t( addToDB, std::move( show ), path, std::move( lang ),
|
||
|
std::move( show_id ), getDBPattern(), false, dvd,
|
||
|
pw.getWindow() );
|
||
|
t.detach();
|
||
|
pw.mainLoop();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbUpdate() {
|
||
|
ProgressWindow pw( mw->hInst, mw->window );
|
||
|
std::thread t( updateDB, false, pw.getWindow() );
|
||
|
t.detach();
|
||
|
pw.mainLoop();
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbRefresh() {
|
||
|
ProgressWindow pw( mw->hInst, mw->window );
|
||
|
std::thread t( refreshDB, false, pw.getWindow() );
|
||
|
t.detach();
|
||
|
pw.mainLoop();
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbClean() {
|
||
|
cleanDB();
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbManage() {
|
||
|
DatabaseWindow dw( mw->hInst, mw->languages, mw->window );
|
||
|
dw.mainLoop();
|
||
|
}
|
||
|
|
||
|
void MainWindow::dbPattern() {
|
||
|
auto pattern = getDBPattern();
|
||
|
PatternWindow pw( mw->hInst, pattern.c_str(), mw->window );
|
||
|
pw.mainLoop();
|
||
|
if ( pw.accepted() )
|
||
|
changeDBPattern( pw.getPattern() );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void MainWindow::patternHelp() {
|
||
|
MessageBoxW(
|
||
|
NULL,
|
||
|
L"%filename - original filename (without type extension)\n\n"
|
||
|
"%show - show name from thetvdb\n\n"
|
||
|
"%epname - episode name from thetvdb\n\n"
|
||
|
"%season - season number\n\n"
|
||
|
"%episode - episode number\n\n"
|
||
|
"Both season number and episode number can be padded with zeros, just "
|
||
|
"add width of padding"
|
||
|
" right after %, like this: %2season.\n\n"
|
||
|
"Default pattern is \"%filename - %epname\", you might want to change "
|
||
|
"this to"
|
||
|
" \"S%2seasonE%2episode - %epname\" or \"%show - S%2seasonE%2episode - "
|
||
|
"%epname\"",
|
||
|
L"Test", MB_OK );
|
||
|
return;
|
||
|
}
|