Skip to content

Commit 46c4514

Browse files
committed
Add 'Add server' button to server list popup
* Fix crash in WinServerIconCache
1 parent e3df6cb commit 46c4514

File tree

12 files changed

+231
-243
lines changed

12 files changed

+231
-243
lines changed

Data/servers.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@
372372
</Actions>
373373
<Result ImageUrlTemplate="stub" ThumbUrlTemplate="stub" DownloadUrlTemplate="stub"/>
374374
</Server>
375-
<Server Name="imgbb.com" MaxFileSize="32000000" Plugin="imgbb" Authorize="1" PasswordLabel="API key" WebsiteUrl="https://imgbb.com/"
375+
<Server Name="imgbb.com" MaxFileSize="33554432" Plugin="imgbb" Authorize="1" PasswordLabel="API key" WebsiteUrl="https://imgbb.com/"
376376
RegistrationUrl="https://imgbb.com/signup">
377377
<Actions>
378378
</Actions>
@@ -538,7 +538,7 @@
538538
<Server Name="dubz.co" Authorize="1" Type="video" Plugin="dubz" WebsiteUrl="https://dubz.co/" RegistrationUrl="https://dubz.co/register" LoginLabel="Email">
539539
<Info>
540540
<SupportedFormats>
541-
<FormatGroup MaxFileSize="100000000" UserTypes="anon">
541+
<FormatGroup MaxFileSize="104857600" UserTypes="anon">
542542
<Format MimeType="video/mp4">*.mp4</Format>
543543
<Format MimeType="video/quicktime">*.mov</Format>
544544
<Format MimeType="audio/mpeg">*.mp3</Format>

Lang/locale/ru/LC_MESSAGES/imageuploader.po

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ msgstr "Доступ:"
204204

205205
#: ../Source/Gui/Controls/ServerListView.cpp:35
206206
msgid "Account"
207-
msgstr "Аккаунт нужен"
207+
msgstr "Акк."
208208

209209
#: ../Source/Gui/Dialogs/UploadSettings.cpp:717
210210
msgid "Account is not enabled"

Source/Core/WinServerIconCache.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,20 @@ void WinServerIconCache::preLoadIcons(int dpi) {
135135
}
136136

137137
WinServerIconCache::ImageListWithIndexes WinServerIconCache::getImageList(int dpi) {
138-
std::lock_guard lk(cacheMutex_);
139-
auto it = imageLists_.find(dpi);
140-
if (it != imageLists_.end()) {
141-
return std::make_pair(it->second.first->m_hImageList, it->second.second);
138+
{
139+
std::lock_guard lk(cacheMutex_);
140+
auto it = imageLists_.find(dpi);
141+
if (it != imageLists_.end()) {
142+
return std::make_pair(it->second.first->m_hImageList, it->second.second);
143+
}
142144
}
143145
loadIcons(dpi);
144-
it = imageLists_.find(dpi);
145-
if (it != imageLists_.end()) {
146-
return std::make_pair(it->second.first->m_hImageList, it->second.second);
146+
{
147+
std::lock_guard lk(cacheMutex_);
148+
auto it = imageLists_.find(dpi);
149+
if (it != imageLists_.end()) {
150+
return std::make_pair(it->second.first->m_hImageList, it->second.second);
151+
}
147152
}
148153
return {};
149154
}

Source/GUI.rc

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,18 @@ BEGIN
151151
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,39,237,10
152152
END
153153

154-
IDD_SERVERLISTPOPUP DIALOGEX 0, 0, 429, 242
154+
IDD_SERVERLISTPOPUP DIALOGEX 0, 0, 473, 242
155155
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_SYSMENU | WS_THICKFRAME
156156
EXSTYLE WS_EX_CONTROLPARENT
157157
FONT 8, "MS Shell Dlg", 0, 0, 0x0
158158
BEGIN
159-
CONTROL "#all",IDC_ALLTYPESRADIO,"Button",BS_AUTORADIOBUTTON,3,0,64,10
160-
CONTROL "#image",IDC_IMAGERADIO,"Button",BS_AUTORADIOBUTTON,73,0,75,10
161-
CONTROL "#file",IDC_FILERADIO,"Button",BS_AUTORADIOBUTTON,154,0,65,10
162-
CONTROL "#video",IDC_VIDEORADIO,"Button",BS_AUTORADIOBUTTON,226,0,75,10
163-
CONTROL "",IDC_SERVERLISTCONTROL,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,3,12,423,206
164-
EDITTEXT IDC_SEARCHQUERYEDIT,3,221,129,14,ES_AUTOHSCROLL
159+
CONTROL "#all",IDC_ALLTYPESRADIO,"Button",BS_AUTORADIOBUTTON,6,2,64,10
160+
CONTROL "#image",IDC_IMAGERADIO,"Button",BS_AUTORADIOBUTTON,73,2,75,10
161+
CONTROL "#file",IDC_FILERADIO,"Button",BS_AUTORADIOBUTTON,154,2,65,10
162+
CONTROL "#video",IDC_VIDEORADIO,"Button",BS_AUTORADIOBUTTON,226,2,75,10
163+
CONTROL "",IDC_SERVERLISTCONTROL,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,6,15,461,206
164+
EDITTEXT IDC_SEARCHQUERYEDIT,6,224,129,14,ES_AUTOHSCROLL
165+
PUSHBUTTON "#add",IDC_ADDBUTTON,363,224,96,14
165166
END
166167

167168

@@ -218,9 +219,10 @@ BEGIN
218219

219220
IDD_SERVERLISTPOPUP, DIALOG
220221
BEGIN
221-
LEFTMARGIN, 3
222-
RIGHTMARGIN, 426
223-
BOTTOMMARGIN, 240
222+
LEFTMARGIN, 6
223+
RIGHTMARGIN, 467
224+
TOPMARGIN, 2
225+
BOTTOMMARGIN, 238
224226
END
225227
END
226228
#endif // APSTUDIO_INVOKED
@@ -2290,7 +2292,7 @@ BEGIN
22902292
BLOCK "040904b0"
22912293
BEGIN
22922294
VALUE "CompanyName", "Sergey Svistunov"
2293-
VALUE "FileDescription", "Uptooda (GUI)"
2295+
VALUE "FileDescription", "Uptooda"
22942296
VALUE "FileVersion", "1.3.3.0"
22952297
VALUE "InternalName", "UptoodaGUI"
22962298
VALUE "LegalCopyright", "� 2007-2025 Sergey Svistunov (https://svistunov.dev)"

Source/Gui/Controls/ServerListView.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,16 @@ BOOL CServerListView::SubclassWindow(HWND hWnd) {
2727
}
2828

2929
void CServerListView::Init() {
30-
SetItemCount(model_->getCount());
31-
3230
AddColumn(TR("Server"), tcServerName);
3331
AddColumn(TR("Max. file size"), tcMaxFileSize);
3432
AddColumn(TR("Storage time"), tcStorageTime);
3533
AddColumn(TR("Account"), tcAccount);
3634
AddColumn(TR("File formats"), tcFileFormats);
3735

38-
int dpi = DPIHelper::GetDpiForDialog(m_hWnd);
36+
setColumnWidths();
37+
createResources();
3938

40-
SetColumnWidth(tcServerName, MulDiv(130, dpi, USER_DEFAULT_SCREEN_DPI));
41-
SetColumnWidth(tcMaxFileSize, MulDiv(100, dpi, USER_DEFAULT_SCREEN_DPI));
42-
SetColumnWidth(tcStorageTime, MulDiv(80, dpi, USER_DEFAULT_SCREEN_DPI));
43-
SetColumnWidth(tcAccount, MulDiv(50, dpi, USER_DEFAULT_SCREEN_DPI));
44-
SetColumnWidth(tcFileFormats, MulDiv(190, dpi, USER_DEFAULT_SCREEN_DPI));
45-
46-
auto iconsWithIndexes = serverIconCache_->getImageList(dpi);
47-
serverIconImageList_ = iconsWithIndexes.first;
48-
serverIconImageListIndexes_ = std::move(iconsWithIndexes.second);
49-
ModifyStyle(0, LVS_SHAREIMAGELISTS, LVS_SHAREIMAGELISTS);
50-
SetImageList(serverIconImageList_, LVSIL_SMALL);
39+
SetItemCount(model_->getCount());
5140
}
5241

5342
LRESULT CServerListView::OnGetDispInfo(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) {
@@ -119,10 +108,36 @@ LRESULT CServerListView::OnListViewNMCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL&
119108
return 0;
120109
}
121110

111+
LRESULT CServerListView::OnMyDpiChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
112+
setColumnWidths();
113+
createResources();
114+
return 0;
115+
}
116+
122117
void CServerListView::onRowChanged(size_t index) {
123118
PostMessage(LVM_REDRAWITEMS, index, index);
124119
}
125120

121+
122+
void CServerListView::setColumnWidths() {
123+
int dpi = DPIHelper::GetDpiForDialog(m_hWnd);
124+
SetColumnWidth(tcServerName, MulDiv(140, dpi, USER_DEFAULT_SCREEN_DPI));
125+
SetColumnWidth(tcMaxFileSize, MulDiv(115, dpi, USER_DEFAULT_SCREEN_DPI));
126+
SetColumnWidth(tcStorageTime, MulDiv(100, dpi, USER_DEFAULT_SCREEN_DPI));
127+
SetColumnWidth(tcAccount, MulDiv(50, dpi, USER_DEFAULT_SCREEN_DPI));
128+
SetColumnWidth(tcFileFormats, MulDiv(200, dpi, USER_DEFAULT_SCREEN_DPI));
129+
}
130+
131+
132+
void CServerListView::createResources() {
133+
int dpi = DPIHelper::GetDpiForDialog(m_hWnd);
134+
auto iconsWithIndexes = serverIconCache_->getImageList(dpi);
135+
serverIconImageList_ = iconsWithIndexes.first;
136+
serverIconImageListIndexes_ = std::move(iconsWithIndexes.second);
137+
ModifyStyle(0, LVS_SHAREIMAGELISTS, LVS_SHAREIMAGELISTS);
138+
SetImageList(serverIconImageList_, LVSIL_SMALL);
139+
}
140+
126141
int CServerListView::FindItemByString(LPCWSTR searchText, int startIndex, DWORD flags) {
127142
if (!searchText || !model_) {
128143
return -1;

Source/Gui/Controls/ServerListView.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class CServerListView :
2020
BEGIN_MSG_MAP(CServerListView)
2121
REFLECTED_NOTIFY_CODE_HANDLER(LVN_GETDISPINFO, OnGetDispInfo)
2222
REFLECTED_NOTIFY_CODE_HANDLER(LVN_ODFINDITEM, OnOdFindItem)
23+
MESSAGE_HANDLER(WM_MY_DPICHANGED, OnMyDpiChanged)
2324
//REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnListViewNMCustomDraw)
2425
//REFLECTED_NOTIFY_CODE_HANDLER(LVN_DELETEITEM, OnDeleteItem)
2526
//REFLECTED_NOTIFY_CODE_HANDLER(LVN_DELETEALLITEMS, OnDeleteItem)
@@ -36,9 +37,13 @@ class CServerListView :
3637
LRESULT OnGetDispInfo(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
3738
LRESULT OnOdFindItem(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
3839
LRESULT OnListViewNMCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
40+
LRESULT OnMyDpiChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
41+
3942
protected:
4043
ServerListModel* model_;
4144
void onRowChanged(size_t index);
45+
void setColumnWidths();
46+
void createResources();
4247
CImageList serverIconImageList_;
4348
std::vector<int> serverIconImageListIndexes_;
4449
WinServerIconCache* serverIconCache_;

Source/Gui/Dialogs/ServerListPopup.cpp

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "ServerListPopup.h"
2222

2323
#include <strsafe.h>
24+
#include <dwmapi.h>
2425

2526
#include "Gui/GuiTools.h"
2627
#include "Func/WinUtils.h"
@@ -30,6 +31,9 @@
3031
#include "Core/AbstractServerIconCache.h"
3132
#include "Gui/Helpers/DPIHelper.h"
3233
#include "Gui/Models/ServerListModel.h"
34+
#include "AddFtpServerDialog.h"
35+
#include "AddDirectoryServerDialog.h"
36+
#include "Func/MyEngineList.h"
3337

3438
namespace {
3539

@@ -50,7 +54,6 @@ CServerListPopup::CServerListPopup(CMyEngineList* engineList, WinServerIconCache
5054
isChildWindow_ = isChildWindow;
5155
hMyDlgTemplate_ = nullptr;
5256
isPopingUp_ = false;
53-
BasicSettings* settings = ServiceLocator::instance()->basicSettings();
5457
}
5558

5659
CServerListPopup::~CServerListPopup()
@@ -65,14 +68,21 @@ void CServerListPopup::TranslateUI() {
6568
TRCC(IDC_IMAGERADIO, "serverlist.servertype", "Image");
6669
TRCC(IDC_FILERADIO, "serverlist.servertype", "File");
6770
TRCC(IDC_VIDEORADIO, "serverlist.servertype", "Video");
71+
TRC(IDC_ADDBUTTON, "Add server");
6872
}
6973

7074
LRESULT CServerListPopup::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
7175
{
76+
DWMNCRENDERINGPOLICY policy = DWMNCRP_DISABLED;
77+
DwmSetWindowAttribute(m_hWnd, DWMWA_NCRENDERING_POLICY, &policy, sizeof(policy));
78+
7279
DlgResize_Init(true, true, 0); // resizable dialog without "griper"
7380
DoDataExchange(FALSE);
74-
listView_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
81+
7582
TranslateUI();
83+
addServerButton_.SetButtonStyle(BS_SPLITBUTTON);
84+
85+
listView_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
7686

7787
if (selectedServerType_ == CUploadEngineData::TypeImageServer) {
7888
imageTypeRadioButton_.SetCheck(BST_CHECKED);
@@ -92,7 +102,9 @@ LRESULT CServerListPopup::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam,
92102
createResources();
93103
updateServerList();
94104

95-
applyFilter();
105+
applyFilter(false);
106+
107+
selectServerByName(U2W(engineList_->byIndex(serverIndex_)->Name));
96108
listView_.SetFocus();
97109

98110
return FALSE;
@@ -105,6 +117,7 @@ LRESULT CServerListPopup::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
105117

106118
LRESULT CServerListPopup::OnDpiChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
107119
createResources();
120+
listView_.SendMessage(WM_MY_DPICHANGED, wParam);
108121
return 0;
109122
}
110123

@@ -135,7 +148,6 @@ void CServerListPopup::setServersMask(int mask) {
135148

136149
void CServerListPopup::notifyChange()
137150
{
138-
//::SendMessage(GetParent(), WM_SERVERSELECTCONTROL_CHANGE, reinterpret_cast<WPARAM>(m_hWnd), 0);
139151
if (onChangeCallback_)
140152
{
141153
onChangeCallback_(this);
@@ -144,7 +156,6 @@ void CServerListPopup::notifyChange()
144156

145157
void CServerListPopup::notifyServerListChanged()
146158
{
147-
//::SendMessage(GetParent(), WM_SERVERSELECTCONTROL_SERVERLIST_CHANGED, reinterpret_cast<WPARAM>(m_hWnd), 0);
148159
}
149160

150161
void CServerListPopup::updateServerList()
@@ -163,6 +174,12 @@ void CServerListPopup::createResources() {
163174
const int iconWidth = DPIHelper::GetSystemMetricsForDpi(SM_CXSMICON, dpi);
164175
const int iconHeight = DPIHelper::GetSystemMetricsForDpi(SM_CYSMICON, dpi);
165176

177+
if (addServerButtonIcon_) {
178+
addServerButtonIcon_.DestroyIcon();
179+
}
180+
181+
addServerButtonIcon_.LoadIconWithScaleDown(MAKEINTRESOURCE(IDI_ICONADDITEM), iconWidth, iconHeight);
182+
addServerButton_.SetIcon(addServerButtonIcon_);
166183
}
167184

168185
void CServerListPopup::setOnChangeCallback(std::function<void(CServerListPopup*)> cb) {
@@ -499,7 +516,17 @@ LRESULT CServerListPopup::OnSearchQueryEditChanged(WORD wNotifyCode, WORD wID, H
499516
return 0;
500517
}
501518

502-
void CServerListPopup::applyFilter() {
519+
LRESULT CServerListPopup::OnBnClickedAddServerButton(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
520+
showAddServerButtonMenu(hWndCtl);
521+
return 0;
522+
}
523+
524+
LRESULT CServerListPopup::OnBnDropdownAddServerButton(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) {
525+
showAddServerButtonMenu(GetDlgItem(IDC_ADDBUTTON));
526+
return 0;
527+
}
528+
529+
void CServerListPopup::applyFilter(bool selectItem) {
503530
int mask = 0;
504531

505532
if (imageTypeRadioButton_.GetCheck() == BST_CHECKED) {
@@ -519,5 +546,84 @@ void CServerListPopup::applyFilter() {
519546
filter.query = W2U(query);
520547
filter.typeMask = mask;
521548
serverListModel_->applyFilter(filter);
522-
listView_.SelectItem(0);
549+
if (selectItem) {
550+
listView_.SelectItem(0);
551+
}
552+
}
553+
554+
void CServerListPopup::clearFilter() {
555+
queryEditControl_.SetWindowText(_T(""));
556+
allTypesRadioButton_.SetCheck(BST_CHECKED);
557+
imageTypeRadioButton_.SetCheck(BST_UNCHECKED);
558+
fileTypeRadioButton_.SetCheck(BST_UNCHECKED);
559+
videoTypeRadioButton_.SetCheck(BST_UNCHECKED);
560+
}
561+
562+
void CServerListPopup::selectServerByName(const CString& name) {
563+
const std::string serverName = W2U(name);
564+
size_t count = serverListModel_->getCount();
565+
for (size_t i = 0; i < count; ++i) {
566+
if (serverListModel_->getDataByIndex(i).ued->Name == serverName) {
567+
listView_.SelectItem(i);
568+
return;
569+
}
570+
}
571+
}
572+
573+
void CServerListPopup::showAddServerButtonMenu(HWND control) {
574+
RECT rc;
575+
::GetWindowRect(control, &rc);
576+
POINT menuOrigin = { rc.left, rc.bottom };
577+
578+
CMenu popupMenu;
579+
popupMenu.CreatePopupMenu();
580+
std::wstring itemTitle = str(IuStringUtils::FormatWideNoExcept(TR("Add %s server...")) % L"FTP/SFTP/WebDAV");
581+
popupMenu.AppendMenu(MF_STRING, IDM_ADD_FTP_SERVER, itemTitle.c_str());
582+
popupMenu.AppendMenu(MF_STRING, IDM_ADD_DIRECTORY_AS_SERVER, TR("Add folder as new server..."));
583+
popupMenu.AppendMenu(MF_STRING, IDM_OPEN_SERVERS_FOLDER, TR("Open servers folder"));
584+
585+
TPMPARAMS excludeArea;
586+
ZeroMemory(&excludeArea, sizeof(excludeArea));
587+
excludeArea.cbSize = sizeof(excludeArea);
588+
excludeArea.rcExclude = rc;
589+
popupMenu.TrackPopupMenuEx(TPM_LEFTALIGN | TPM_LEFTBUTTON, menuOrigin.x, menuOrigin.y, m_hWnd, &excludeArea);
590+
}
591+
592+
LRESULT CServerListPopup::OnAddFtpServer(WORD wNotifyCode, WORD wID, HWND hWndCtl) {
593+
CAddFtpServerDialog dlg(engineList_);
594+
if (dlg.DoModal(m_hWnd) == IDOK) {
595+
serverListModel_->updateEngineList();
596+
clearFilter();
597+
applyFilter(false);
598+
selectServerByName(dlg.createdServerName());
599+
listView_.SetFocus();
600+
}
601+
return 0;
602+
}
603+
604+
LRESULT CServerListPopup::OnAddDirectoryAsServer(WORD wNotifyCode, WORD wID, HWND hWndCtl) {
605+
CAddDirectoryServerDialog dlg(engineList_);
606+
if (dlg.DoModal(m_hWnd) == IDOK) {
607+
serverListModel_->updateEngineList();
608+
clearFilter();
609+
applyFilter(false);
610+
selectServerByName(dlg.createdServerName());
611+
listView_.SetFocus();
612+
}
613+
return 0;
614+
}
615+
616+
LRESULT CServerListPopup::OnOpenServersFolder(WORD wNotifyCode, WORD wID, HWND hWndCtl) {
617+
auto* settings = ServiceLocator::instance()->settings<WtlGuiSettings>();
618+
const std::wstring folder = IuCoreUtils::Utf8ToWstring(settings->SettingsFolder + "Servers\\");
619+
try {
620+
WinUtils::ShellOpenFileOrUrl(folder.c_str(), m_hWnd, {}, true);
621+
} catch (const Win32Exception& ex) {
622+
const std::wstring msg = str(
623+
IuStringUtils::FormatWideNoExcept(TR("Cannot open folder '%1%'.\n%2%"))
624+
% folder
625+
% ex.getMessage().GetString());
626+
GuiTools::LocalizedMessageBox(m_hWnd, msg.c_str(), TR("Error"), MB_ICONERROR);
627+
}
628+
return 0;
523629
}

0 commit comments

Comments
 (0)