diff --git a/application.qrc b/application.qrc index 0507184..e4cd3d2 100644 --- a/application.qrc +++ b/application.qrc @@ -8,6 +8,9 @@ res/paymentreq.gif res/icon.ico res/mail.png + res/darkwing.png + res/sdlogo.png + res/sdlogo2.png res/hushdlogo.gif diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index c6dd75d..68b496a 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace std; using namespace boost; @@ -80,11 +81,11 @@ void ChatModel::showMessages() { for(auto &c : this->chatItems) { - qDebug() << "[" << c.second.getTimestamp() << "] " << "<" << c.second.getAddress() << "> :" << c.second.getMemo(); + qDebug() << c.second.toChatLine(); } } -void ChatModel::renderChatBox(Ui::MainWindow* ui, QListWidget &view) +void ChatModel::renderChatBox(Ui::MainWindow* ui, QListView &view) { /*for(auto &c : this->chatItems) { @@ -94,65 +95,59 @@ void ChatModel::renderChatBox(Ui::MainWindow* ui, QListWidget &view) //todo render items to view } -void ChatModel::renderChatBox(Ui::MainWindow* ui, QListWidget *view) +void ChatModel::renderChatBox(Ui::MainWindow* ui, QListView *view) { - - while(view->count() > 0) - { - view->takeItem(0); - } - - QString line = ""; - - for(auto &c : this->chatItems){ - - QDateTime myDateTime; - - myDateTime.setTime_t(c.second.getTimestamp()); + + QStandardItemModel* chat = new QStandardItemModel(); + + + for (auto &c : this->chatItems) + for (auto &p : AddressBook::getInstance()->getAllAddressLabels()) + { + + + //////Render only Memos for selected contacts. Do not render empty Memos //// Render only memos where cid=cid - /// - if ((ui->ContactZaddr->text().trimmed() == c.second.getAddress()) && (c.second.getMemo().startsWith("{") == false) && (c.second.getMemo().isEmpty() == false)) { - // if (c.second.getMemo.find()) - line += QString("[") + myDateTime.toString("dd.MM.yyyy hh:mm:ss ") + QString("] "); - line += QString("<") + QString("Outgoing") + QString("> :\n"); - line += QString(c.second.getMemo()) + QString("\n"); - view->addItem(line); - line =""; - - - ////////////////////////////////// Todo : Render green checkmark for contacts if cid = cid - We have to search for cid in txid/cid list - // QString cid = c.second.getCid(); - - } - - if ((ui->MyZaddr->text().trimmed() == c.second.getAddress()) && (c.second.getMemo().startsWith("{") == false) && (c.second.getMemo().isEmpty() == false)){ - for(auto &p : AddressBook::getInstance()->getAllAddressLabels()){ + if ( + (ui->contactNameMemo->text().trimmed() == c.second.getContact()) && + (c.second.getMemo().startsWith("{") == false) && + (c.second.getMemo().isEmpty() == false) && + (p.getPartnerAddress() == c.second.getAddress()) + + ) + { + + QStandardItem* Items = new QStandardItem(c.second.toChatLine()); + Items->setData("Incoming", Qt::UserRole +1); + chat->appendRow(Items); + + ui->listChat->setModel(chat); + ui->listChat->setItemDelegate(new ListViewDelegate()); + + } - if ((ui->checkBox->isChecked() == true) && (p.getCid() != c.second.getCid())) - { + if ( + (ui->contactNameMemo->text().trimmed() == c.second.getContact()) && + (c.second.getMemo().startsWith("{") == false) && + (c.second.getMemo().isEmpty() == false) && + (p.getMyAddress() == c.second.getAddress()) - }else{ - - // line+= QString("[") + "Warning. Not verified!" + QString("]"); - - - line += QString("[") + myDateTime.toString("dd.MM.yyyy hh:mm:ss ") + QString("] "); - line += QString("<") + QString("incoming") + QString("> :\n"); - line += QString(c.second.getMemo()) + QString("\n"); - view->addItem(line); - line =""; - } - + ) + { + QStandardItem* Items1 = new QStandardItem(c.second.toChatLine()); + Items1->setData("Outgoing", Qt::UserRole +1); + chat->appendRow(Items1); } - + ui->listChat->setModel(chat); + ui->listChat->setItemDelegate(new ListViewDelegate()); + + } - - } } @@ -220,7 +215,7 @@ Tx MainWindow::createTxFromChatPage() { for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) - if (ui->ContactZaddr->text().trimmed() == c.getPartnerAddress()) { + if (ui->contactNameMemo->text().trimmed() == c.getName()) { QString cid = c.getCid(); QString myAddr = c.getMyAddress(); @@ -230,6 +225,7 @@ Tx MainWindow::createTxFromChatPage() { QString hmemo= createHeaderMemo(type,cid,myAddr); QString memo = ui->memoTxtChat->toPlainText().trimmed(); + // ui->memoSizeChat->setLenDisplayLabel();// Todo -> activate lendisplay for chat tx.toAddrs.push_back(ToFields{addr, amt, hmemo}) ; @@ -247,6 +243,9 @@ Tx MainWindow::createTxFromChatPage() { } void MainWindow::sendChatButton() { + + + ////////////////////////////Todo: Check if a Contact is selected////////// // Create a Tx from the values on the send tab. Note that this Tx object @@ -255,7 +254,7 @@ void MainWindow::sendChatButton() { // Memos can only be used with zAddrs. So check that first // for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) - if (ui->ContactZaddr->text().trimmed().isEmpty() || ui->memoTxtChat->toPlainText().trimmed().isEmpty()) { + if (ui->contactNameMemo->text().trimmed().isEmpty() || ui->memoTxtChat->toPlainText().trimmed().isEmpty()) { // auto addr = ""; // if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) { @@ -391,7 +390,7 @@ Tx MainWindow::createTxForSafeContactRequest() { for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) - if (ui->ContactZaddr->text().trimmed() == c.getName()) { + if (ui->contactNameMemo->text().trimmed() == c.getName()) { // QString cid = c.getCid(); // This has to be a new cid for the contact // QString myAddr = c.getMyAddress(); // this should be a new HushChat zaddr diff --git a/src/chatmodel.h b/src/chatmodel.h index fcc68bf..490f336 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -1,15 +1,162 @@ #ifndef CHATMODEL_H #define CHATMODEL_H #include +#include +#include +#include #include #include -#include +#include #include "precompiled.h" #include "mainwindow.h" #include "controller.h" #include "settings.h" #include "camount.h" + +class ListViewDelegate : public QAbstractItemDelegate +{ + int d_radius; + int d_toppadding; + int d_bottompadding; + int d_leftpadding; + int d_rightpadding; + int d_verticalmargin; + int d_horizontalmargin; + int d_pointerwidth; + int d_pointerheight; + float d_widthfraction; + public: + inline ListViewDelegate(QObject *parent = nullptr); + + protected: + inline void paint(QPainter *painter, QStyleOptionViewItem const &option, QModelIndex const &index) const; + inline QSize sizeHint(QStyleOptionViewItem const &option, QModelIndex const &index) const; +}; + +inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegate(parent), d_radius(5), d_toppadding(5), d_bottompadding(3), d_leftpadding(5), d_rightpadding(5), d_verticalmargin(15), d_horizontalmargin(10), d_pointerwidth(10), d_pointerheight(17), d_widthfraction(.7) +{ + +} + +inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem const &option, QModelIndex const &index) const +{ + QTextDocument bodydoc; + QTextOption textOption(bodydoc.defaultTextOption()); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + bodydoc.setDefaultTextOption(textOption); + bodydoc.setDefaultFont(QFont("Roboto", 12)); + QString bodytext(index.data(Qt::DisplayRole).toString()); + bodydoc.setHtml(bodytext); + qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding; + bodydoc.setTextWidth(contentswidth); + qreal bodyheight = bodydoc.size().height(); + bool outgoing = index.data(Qt::UserRole + 1).toString() == "Outgoing"; + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + // uncomment to see the area provided to paint this item + + //painter->drawRect(option.rect); + + painter->translate(option.rect.left() + d_horizontalmargin, option.rect.top() + ((index.row() == 0) ? d_verticalmargin : 0)); + + // background color for chat bubble + QColor bgcolor("#535353"); + if (outgoing) + bgcolor = "#eeeeee"; + + // create chat bubble + QPainterPath pointie; + + // left bottom + pointie.moveTo(0, bodyheight + d_toppadding + d_bottompadding); + + // right bottom + pointie.lineTo(0 + contentswidth + d_pointerwidth + d_leftpadding + d_rightpadding - d_radius, + bodyheight + d_toppadding + d_bottompadding); + pointie.arcTo(0 + contentswidth + d_pointerwidth + d_leftpadding + d_rightpadding - 2 * d_radius, + bodyheight + d_toppadding + d_bottompadding - 2 * d_radius, + 2 * d_radius, 2 * d_radius, 270, 90); + + // right top + pointie.lineTo(0 + contentswidth + d_pointerwidth + d_leftpadding + d_rightpadding, 0 + d_radius); + pointie.arcTo(0 + contentswidth + d_pointerwidth + d_leftpadding + d_rightpadding - 2 * d_radius, 0, + 2 * d_radius, 2 * d_radius, 0, 90); + + // left top + pointie.lineTo(0 + d_pointerwidth + d_radius, 0); + pointie.arcTo(0 + d_pointerwidth, 0, 2 * d_radius, 2 * d_radius, 90, 90); + + // left bottom almost (here is the pointie) + pointie.lineTo(0 + d_pointerwidth, bodyheight + d_toppadding + d_bottompadding - d_pointerheight); + pointie.closeSubpath(); + + // rotate bubble for outgoing messages + if (outgoing) + { + painter->translate(option.rect.width() - pointie.boundingRect().width() - d_horizontalmargin - d_pointerwidth, 0); + painter->translate(pointie.boundingRect().center()); + painter->rotate(180); + painter->translate(-pointie.boundingRect().center()); + } + + // now paint it! + painter->setPen(QPen(bgcolor)); + painter->drawPath(pointie); + painter->fillPath(pointie, QBrush(bgcolor)); + + // rotate back or painter is going to paint the text rotated... + if (outgoing) + { + painter->translate(pointie.boundingRect().center()); + painter->rotate(-180); + painter->translate(-pointie.boundingRect().center()); + } + + // set text color used to draw message body + QAbstractTextDocumentLayout::PaintContext ctx; + if (outgoing) + ctx.palette.setColor(QPalette::Text, QColor("black")); + else + ctx.palette.setColor(QPalette::Text, QColor("white")); + + // draw body text + painter->translate((outgoing ? 0 : d_pointerwidth) + d_leftpadding, 0); + bodydoc.documentLayout()->draw(painter, ctx); + + painter->restore(); +} + +inline QSize ListViewDelegate::sizeHint(QStyleOptionViewItem const &option, QModelIndex const &index) const +{ + QTextDocument bodydoc; + QTextOption textOption(bodydoc.defaultTextOption()); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + bodydoc.setDefaultTextOption(textOption); + bodydoc.setDefaultFont(QFont("Roboto", 12)); + QString bodytext(index.data(Qt::DisplayRole).toString()); + bodydoc.setHtml(bodytext); + + // the width of the contents are the (a fraction of the window width) minus (margins + padding + width of the bubble's tail) + qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding; + + // set this available width on the text document + bodydoc.setTextWidth(contentswidth); + + QSize size(bodydoc.idealWidth() + d_horizontalmargin + d_pointerwidth + d_leftpadding + d_rightpadding, + bodydoc.size().height() + d_bottompadding + d_toppadding + d_verticalmargin + 1); // I dont remember why +1, haha, might not be necessary + + if (index.row() == 0) // have extra margin at top of first item + size += QSize(0, d_verticalmargin); + + return size; +} + + + + + class ChatItem { private: @@ -117,6 +264,15 @@ class ChatItem _outgoing = true; } + QString toChatLine() + { + QDateTime myDateTime; + myDateTime.setTime_t(_timestamp); + QString line = QString("[") + myDateTime.toString("d.M.yy hh:mm") + QString("] ") ; + line += QString("") + QString(_memo) + QString("\n\n"); + return line; + } + ~ChatItem() { /*delete timestamp; @@ -145,8 +301,8 @@ class ChatModel void setItems(std::map items); QString zaddr(); void setItems(std::vector items); - void renderChatBox(Ui::MainWindow* ui, QListWidget &view); - void renderChatBox(Ui::MainWindow* ui, QListWidget *view); + void renderChatBox(Ui::MainWindow* ui, QListView &view); + void renderChatBox(Ui::MainWindow* ui, QListView *view); void showMessages(); void clear(); void addMessage(ChatItem item); diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp index 0e9a6ea..a19fe1c 100644 --- a/src/contactmodel.cpp +++ b/src/contactmodel.cpp @@ -2,15 +2,22 @@ #include "addressbook.h" #include "mainwindow.h" -void ContactModel::renderContactList(QListWidget* view) -{ - while(view->count() > 0) - { - view->takeItem(0); - } +void ContactModel::renderContactList(QListView* view) +{ // QStandardItem(const QIcon & icon, const QString & text) + QStandardItemModel* contact = new QStandardItemModel(); + //} for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) { - view->addItem(c.getName()); + + //QStandardItem* Items = new QStandardItem(); + QStandardItem* Items1 = new QStandardItem(QIcon("res/darkwing.png"),c.getName()); + // contact->appendRow(Items); + contact->appendRow(Items1); + view->setModel(contact); + view->setIconSize(QSize(80,100)); + view->setUniformItemSizes(true); + view->setDragDropMode(QAbstractItemView::DropOnly);; + } diff --git a/src/contactmodel.h b/src/contactmodel.h index 886b285..b97cc8a 100644 --- a/src/contactmodel.h +++ b/src/contactmodel.h @@ -74,7 +74,7 @@ class ContactModel { public: ContactModel() {} - void renderContactList(QListWidget* view); + void renderContactList(QListView* view); }; #endif \ No newline at end of file diff --git a/src/controller.cpp b/src/controller.cpp index 2fe9b52..577d438 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -881,24 +881,34 @@ void Controller::refreshTransactions() { memo = QString::fromStdString(o["memo"]); QString cid; + QString contact; + for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) - if ((ui->ContactZaddr->text().trimmed() == c.getPartnerAddress()) || (ui->MyZaddr->text().trimmed() == c.getMyAddress())) { + { + if (ui->contactNameMemo->text().trimmed() == c.getName()) { cid = c.getCid(); - }else {cid = "";} + }else {cid = "";} + + if (address == c.getPartnerAddress()){ + contact = c.getName(); + }else{ contact = "";} + ChatItem item = ChatItem( datetime, address, - QString(""), + contact, memo, cid, // we have to set the cid here, its included in our Addressbook for this contact - txid - // true // is an outgoing message + txid, + true // is an outgoing message ); chatModel->addMessage(item); - } - + + } + + } items.push_back(TransactionItemDetail{address, amount, memo}); total_amount = total_amount + amount; @@ -912,7 +922,6 @@ void Controller::refreshTransactions() { }else{ - addresses.push_back(item.address); } } @@ -957,18 +966,34 @@ void Controller::refreshTransactions() { else cid = ""; } - + + QString contact; + for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) + // for (auto &p : this->chatItems) + { + + if (address == c.getMyAddress()){ + contact = c.getName(); + qDebug()<< "Addressbuch Addresse: " << c.getMyAddress(); + qDebug()<< "Addresse: " << address; + + }else{ contact = "ELSE";} + ChatItem item = ChatItem( datetime, address, - QString(""), + contact, memo, cid, // we have to set the cid here, its included in the headermemo - txid + txid, + false ); - // qDebug()<< "Message CID: " << cid; - chatModel->addMessage(item); + // qDebug()<< "KontaktName: " << contact; + + // qDebug()<< "Addressbuch Addresse: " << c.getMyAddress(); + chatModel->addMessage(item); +} } } @@ -990,7 +1015,7 @@ void Controller::refreshTransactions() { // Update model data, which updates the table view transactionsTableModel->replaceData(txdata); - chatModel->renderChatBox(ui, ui->listChatMemo); + chatModel->renderChatBox(ui, ui->listChat); refreshContacts( ui->listContactWidget @@ -998,13 +1023,13 @@ void Controller::refreshTransactions() { }); } -void Controller::refreshChat(QListWidget *listWidget) +void Controller::refreshChat(QListView *listWidget) { chatModel->renderChatBox(ui, listWidget); } -void Controller::refreshContacts(QListWidget *listWidget) +void Controller::refreshContacts(QListView *listWidget) { contactModel->renderContactList(listWidget); } diff --git a/src/controller.h b/src/controller.h index 4a0835f..bc56587 100644 --- a/src/controller.h +++ b/src/controller.h @@ -72,8 +72,8 @@ public: void refreshGBPCAP(); void refreshAUDCAP(); - void refreshChat(QListWidget *listWidget); - void refreshContacts(QListWidget *listWidget); + void refreshChat(QListView *listWidget); + void refreshContacts(QListView *listWidget); void executeStandardUITransaction(Tx tx); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f17bfc9..0104f56 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -39,8 +39,12 @@ MainWindow::MainWindow(QWidget *parent) : ui->setupUi(this); - ui->checkBox->setChecked(true); + // ui->checkBox->setChecked(true); logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite-wallet.log")); + ui->memoTxtChat->setAutoFillBackground(false); + // ui->memoTxtChat->setStyleSheet(QString::fromUtf8("background-color: rgb(224, 224, 224);")); + ui->memoTxtChat->setPlaceholderText("Send Message"); + ui->memoTxtChat->setTextColor(Qt::white); // Status Bar setupStatusBar(); @@ -901,6 +905,17 @@ void MainWindow::setupTransactionsTab() { }); // Set up context menu on transactions tab + auto theme = Settings::getInstance()->get_theme_name(); + if (theme == "dark"){ + ui->listChat->setStyleSheet("background-image: url(res/sdlogo.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover"); + }else{ui->listChat->setStyleSheet("background-image: url(res/sdlogo2.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover");} + ui->listChat->setResizeMode(QListView::Adjust); + ui->listChat->setWordWrap(true); + ui->listChat->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + ui->listChat->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui->listChat->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui->listChat->setMinimumSize(200,350); + ui->listChat->show(); ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu); // Table right click QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) { @@ -993,20 +1008,25 @@ void MainWindow::setupchatTab() { ///////// Set selected Zaddr for Chat with Doubleklick QObject::connect(ui->listContactWidget, &QTableView::clicked, [=] () { + QModelIndex index = ui->listContactWidget->currentIndex(); QString label_contact = index.data(Qt::DisplayRole).toString(); for(auto &p : AddressBook::getInstance()->getAllAddressLabels()) if (label_contact == p.getName()) { - ui->ContactZaddr->setText(p.getPartnerAddress()); - ui->MyZaddr->setText(p.getMyAddress()); + // ui->ContactZaddr->setText(p.getPartnerAddress()); + // ui->MyZaddr->setText(p.getMyAddress()); ui->contactNameMemo->setText(p.getName()); - ui->contactCid->setText(p.getCid()); + ui->memoTxtChat->clear(); rpc->refresh(true); + // updateChat(); } }); + + + } ChatMemoEdit::ChatMemoEdit(QWidget* parent) : QPlainTextEdit(parent) { @@ -1052,13 +1072,14 @@ void ChatMemoEdit::setSendChatButton(QPushButton* button) { void MainWindow::updateChat() { - rpc->refreshChat(ui->listChatMemo); + rpc->refreshChat(ui->listChat); + rpc->refresh(true); + } void MainWindow::updateContacts() { - qDebug() << "Called MainWindow::updateContacts()"; - rpc->refreshContacts(ui->listContactWidget); + //rpc->refreshContacts(ui->listContactWidget); } void MainWindow::addNewZaddr(bool sapling) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 7114eda..1110f67 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -54,6 +54,7 @@ public: bool isWebsocketListening(); void createWebsocket(QString wormholecode); void stopWebsocket(); + void balancesReady(); void payhushURI(QString uri = "", QString myAddr = ""); @@ -92,8 +93,9 @@ private: void setupBalancesTab(); void setuphushdTab(); void setupchatTab(); - void updateChat(); + void updateContacts(); + void updateChat(); void setupSettingsModal(); void setupStatusBar(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 3196dff..e58e4ad 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1328,7 +1328,7 @@ HushChat - + 0 @@ -1351,21 +1351,24 @@ <html><head/><body><p align="center">Hushchat Contactlist</p></body></html> - + 340 - 410 + 460 921 - 128 + 131 + + font: 11pt "Noto Color Emoji"; + - 1200 - 540 + 1190 + 610 47 17 @@ -1390,36 +1393,11 @@ <html><head/><body><p align="center"><br/></p></body></html> - - - true - - - - 340 - 40 - 921 - 371 - - - - QAbstractItemView::NoEditTriggers - - - false - - - Qt::IgnoreAction - - - QAbstractItemView::NoSelection - - - 1130 - 590 + 710 + 610 114 25 @@ -1437,45 +1415,6 @@ false - - - - 350 - 550 - 81 - 17 - - - - Send To : - - - - - - 350 - 580 - 81 - 17 - - - - <html><head/><body><p>My zaddr :</p></body></html> - - - - - - 420 - 550 - 691 - 20 - - - - - - @@ -1498,58 +1437,6 @@ false - - - - 420 - 580 - 691 - 20 - - - - - - - - - - 720 - 20 - 331 - 20 - - - - <html><head/><body><p align="center"><br/></p></body></html> - - - - - - 590 - 20 - 131 - 20 - - - - <html><head/><body><p align="center">Conversation ID:</p></body></html> - - - - - - 980 - 0 - 271 - 23 - - - - Render only authenticated messages - - @@ -1563,6 +1450,40 @@ <html><head/><body><p align="center">Contact Name:</p></body></html> + + + + 340 + 40 + 921 + 421 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + QAbstractItemView::NoEditTriggers + + + QListView::Adjust + + + 0 + + + false + + + true + + @@ -1734,11 +1655,6 @@ - - MemoEdit - QPlainTextEdit -
memoedit.h
-
AddressCombo QComboBox