#ifndef CUSTOM_FILE_DIALOG_H #define CUSTOM_FILE_DIALOG_H #include #include #include #include #include #include #include #include "base/HGBase.h" #if !defined (HG_CMP_MSC) #define USE_FILE_DLG_WITHOUT_PROMPT #endif template class custom_file_dlg { QLineEdit* edit_; QLineEdit* new_; QPushButton *save_; QFileDialog *fdlg_; QListView *list_; enum find_cls { FIND_BUTTON = 1, FIND_LINE_EDIT, FIND_LIST, }; typedef struct _find_ctrl { int cls; std::string title; QObject *found; }FINDCTRL, *LPFINDCTRL; static bool find_ctrls(QObject* obj, LPFINDCTRL ret) { if(ret->cls == FIND_BUTTON) { QPushButton* btn = dynamic_cast(obj); if(btn) { std::string t(btn->text().toStdString()); if(ret->title.empty() || t == ret->title) // "\344\277\235\345\255\230(&S)") { ret->found = obj; return true; } } QButtonGroup* grp = dynamic_cast(obj); if(grp) { printf("Found button-group with %d buttons\n", grp->buttons().size()); QList btns = grp->buttons(); for(auto& b : btns) { btn = dynamic_cast(b); if(btn) { std::string t(btn->text().toStdString()); if(ret->title.empty() || t == ret->title) // "\344\277\235\345\255\230(&S)") { ret->found = obj; return true; } } } } } else if(ret->cls == FIND_LINE_EDIT) { QLineEdit* edit = dynamic_cast(obj); if(edit) { std::string t(edit->text().toStdString()); if(ret->title.empty() || t == ret->title) // "\344\277\235\345\255\230(&S)") { ret->found = obj; return true; } } } else if(ret->cls == FIND_LIST) { QListView *v = dynamic_cast(obj); if(v) { std::string t(v->objectName().toStdString()); if(ret->title.empty() && ret->title.empty()) // || t == ret->title) { ret->found = obj; return true; } } } QListWidget *l = dynamic_cast(obj); if(l) { printf("Found list widget\n"); } else { QListView *v = dynamic_cast(obj); if(v) printf("Found list view: %s\n", v->objectName().toStdString().c_str()); } QObjectList objs(obj->children()); for(auto& o : objs) { if(find_ctrls(o, ret)) return true; } return false; } QPushButton* save_button(void){return save_;} QLineEdit* input_edit(bool org){return org ? edit_ : new_;} QListView* file_list(void){return list_;} void replace_input(QLineEdit* from, QLineEdit* tobe) { fdlg_->layout()->replaceWidget(from, tobe); from->hide(); tobe->show(); } protected slots: virtual void on_file_dialog_textChanged(const QString &path) = 0; virtual void on_file_dialog_returnPressed() = 0; protected: custom_file_dlg() : edit_(nullptr), new_(nullptr), save_(nullptr), fdlg_(nullptr), list_(nullptr) { } ~custom_file_dlg() { } public: static QLineEdit* find_input_box(QFileDialog* host) { FINDCTRL fc; QObjectList objs(host->children()); fc.cls = FIND_LINE_EDIT; fc.found = nullptr; for(auto& o : objs) { QString objName = o->objectName(); if(custom_file_dlg::find_ctrls(o, &fc)) break; } return dynamic_cast(fc.found); } static QPushButton* find_button(QFileDialog* host, const char* title) { FINDCTRL fc; QObjectList objs(host->children()); fc.cls = FIND_BUTTON; fc.title = (title && *title) ? title : ""; fc.found = nullptr; for(auto& o : objs) { QString objName = o->objectName(); if(custom_file_dlg::find_ctrls(o, &fc)) break; } return dynamic_cast(fc.found); } static QListView* find_list(QFileDialog* host, const char* title) { FINDCTRL fc; QObjectList objs(host->children()); fc.cls = FIND_LIST; fc.title = (title && *title) ? title : ""; fc.found = nullptr; for(auto& o : objs) { if(custom_file_dlg::find_ctrls(o, &fc)) break; } return dynamic_cast(fc.found); } protected: bool init_custom_file_dlg(QFileDialog* fdlg) { new_ = new QLineEdit(((T*)this)); QRegExp rx("[^\\\\/:*?\"<>|]+$"); QRegExpValidator *pReg = new QRegExpValidator(rx, fdlg); new_->setValidator(pReg); fdlg_ = fdlg; edit_ = custom_file_dlg::find_input_box(fdlg); save_ = custom_file_dlg::find_button(fdlg, QObject::tr("&Save").toStdString().c_str()); list_ = custom_file_dlg::find_list(fdlg, ""); if(edit_ && save_ && list_) { enable_prompt(false); ((T*)this)->connect(new_, SIGNAL(textChanged(const QString&)), (T*)this, SLOT(on_file_dialog_textChanged(const QString))); ((T*)this)->connect(new_, SIGNAL(returnPressed()), (T*)this, SLOT(on_file_dialog_returnPressed())); ((T*)this)->connect(fdlg, SIGNAL(currentChanged(const QString&)), (T*)this, SLOT(on_file_dialog_textChanged(const QString))); fdlg->setFocus(); new_->setFocus(); } return edit_ && save_; } void enable_prompt(bool enable) { if(edit_) { if(enable) replace_input(new_, edit_); else replace_input(edit_, new_); } } void on_file_name_changed(const QLineEdit* ctrl, const QString& text) { if(ctrl == nullptr) // send by QFileDialog { std::string name(text.toStdString()); size_t pos = name.rfind('/'); if(pos++ != std::string::npos) name.erase(0, pos); new_->setText(QString::fromStdString(name)); } else if(ctrl == edit_ && new_) new_->setText(text); else if(edit_) { QString ext(text), sel_ext(((T*)this)->getSaveExt()); int pos = ext.lastIndexOf('.'); list_->clearSelection(); if(pos == -1) edit_->setText(text + sel_ext); else { ext = ext.right(ext.length() - pos); if(ext.compare(sel_ext, Qt::CaseInsensitive) == 0) edit_->setText(text); else edit_->setText(text + sel_ext); } } if(save_) save_->setEnabled(!text.isEmpty()); } void on_file_name_press_return(void) { emit save_->clicked(); } }; #endif // CUSTOM_FILE_DIALOG_H