From d3e81d5efaaa26bcc5b83a398d9d8612f0115e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Thu, 17 May 2018 15:54:19 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@379 a8b55f48-bf90-11e4-a774-851b48703e85 --- qcd_utils/pult/cdgraphics.cpp | 17 + qcd_utils/pult/cdgraphics.h | 25 ++ qcd_utils/pult/cdgraphics.ui | 19 + qcd_utils/pult/cdpult.qrc | 5 +- qcd_utils/pult/cdpultwindow.cpp | 168 +++++---- qcd_utils/pult/cdpultwindow.h | 29 +- qcd_utils/pult/cdpultwindow.ui | 319 +++++++++++++++-- qcd_utils/pult/cdviewwidget.cpp | 78 ++++ qcd_utils/pult/cdviewwidget.h | 41 +++ qcd_utils/pult/cdviewwidget.ui | 121 +++++++ qcd_utils/pult/icons/document-revert.png | Bin 0 -> 2885 bytes qcd_utils/pult/icons/flame.png | Bin 0 -> 3342 bytes qcd_utils/pult/icons/view-refresh.png | Bin 0 -> 40505 bytes qcd_utils/qcd_core.cpp | 8 +- qcd_utils/qcd_kview.cpp | 124 ------- qcd_utils/qcd_kview.h | 61 ---- qcd_utils/{qcd_kmodel.cpp => qcd_model.cpp} | 372 ++++++++++---------- qcd_utils/{qcd_kmodel.h => qcd_model.h} | 58 +-- qcd_utils/qcd_view.cpp | 214 +++++++++++ qcd_utils/qcd_view.h | 71 ++++ 20 files changed, 1198 insertions(+), 532 deletions(-) create mode 100644 qcd_utils/pult/cdgraphics.cpp create mode 100644 qcd_utils/pult/cdgraphics.h create mode 100644 qcd_utils/pult/cdgraphics.ui create mode 100644 qcd_utils/pult/cdviewwidget.cpp create mode 100644 qcd_utils/pult/cdviewwidget.h create mode 100644 qcd_utils/pult/cdviewwidget.ui create mode 100644 qcd_utils/pult/icons/document-revert.png create mode 100644 qcd_utils/pult/icons/flame.png create mode 100644 qcd_utils/pult/icons/view-refresh.png delete mode 100644 qcd_utils/qcd_kview.cpp delete mode 100644 qcd_utils/qcd_kview.h rename qcd_utils/{qcd_kmodel.cpp => qcd_model.cpp} (51%) rename qcd_utils/{qcd_kmodel.h => qcd_model.h} (60%) create mode 100644 qcd_utils/qcd_view.cpp create mode 100644 qcd_utils/qcd_view.h diff --git a/qcd_utils/pult/cdgraphics.cpp b/qcd_utils/pult/cdgraphics.cpp new file mode 100644 index 0000000..f29d94e --- /dev/null +++ b/qcd_utils/pult/cdgraphics.cpp @@ -0,0 +1,17 @@ +#include "cdgraphics.h" +#include "cdutils_core.h" +#include "qcd_core.h" +#include "qcd_model.h" + + +CDGraphics::CDGraphics(QWidget * parent) : QWidget(parent), Ui::CDGraphics() { + setupUi(this); +} + + +CDGraphics::~CDGraphics() { +} + + +void CDGraphics::reset() { +} diff --git a/qcd_utils/pult/cdgraphics.h b/qcd_utils/pult/cdgraphics.h new file mode 100644 index 0000000..9b83bf2 --- /dev/null +++ b/qcd_utils/pult/cdgraphics.h @@ -0,0 +1,25 @@ +#ifndef CDGRAPHICS_H +#define CDGRAPHICS_H + +#include +#include "ui_cdgraphics.h" + + +class CDGraphics : public QWidget, public Ui::CDGraphics +{ + Q_OBJECT +public: + explicit CDGraphics(QWidget *parent = 0); + ~CDGraphics(); + + void reset(); + +private: + +private slots: + +signals: + +}; + +#endif // CDGRAPHICS_H diff --git a/qcd_utils/pult/cdgraphics.ui b/qcd_utils/pult/cdgraphics.ui new file mode 100644 index 0000000..ec8c364 --- /dev/null +++ b/qcd_utils/pult/cdgraphics.ui @@ -0,0 +1,19 @@ + + + CDGraphics + + + + 0 + 0 + 689 + 459 + + + + CD Pult + + + + + diff --git a/qcd_utils/pult/cdpult.qrc b/qcd_utils/pult/cdpult.qrc index 6558e69..59858dc 100644 --- a/qcd_utils/pult/cdpult.qrc +++ b/qcd_utils/pult/cdpult.qrc @@ -7,5 +7,8 @@ icons/dialog-cancel.png icons/dialog-ok-apply.png icons/timer.png - + icons/document-revert.png + icons/flame.png + icons/view-refresh.png + diff --git a/qcd_utils/pult/cdpultwindow.cpp b/qcd_utils/pult/cdpultwindow.cpp index e374131..f909b72 100644 --- a/qcd_utils/pult/cdpultwindow.cpp +++ b/qcd_utils/pult/cdpultwindow.cpp @@ -1,41 +1,43 @@ -#include +#include "edockwidget.h" #include "cdpultwindow.h" -#include "ui_cdpultwindow.h" #include "cdutils_k.h" #include "cdutils_core.h" #include "qcd_core.h" -#include "qcd_kmodel.h" +#include "qcd_model.h" #include "qcd_modedialog.h" +#include "chunkstream.h" +#include "qvariantedit.h" #include #include -CDPultWindow::CDPultWindow(QWidget *parent) : EMainWindow(parent), ui(new Ui::CDPultWindow) { - CDUtils::CDCore::instance()->initPult(); - qRegisterMetaType("LogIcon"); - log_icons[OKIcon] = QIcon(":/icons/dialog-ok-apply.png"); - log_icons[FailIcon] = QIcon(":/icons/dialog-cancel.png"); - log_icons[WaitIcon] = QIcon(":/icons/timer.png"); - ui->setupUi(this); +CDPultWindow::CDPultWindow(QWidget *parent) : EMainWindow(parent), Ui::CDPultWindow() { + setupUi(this); centralWidget()->hide(); - setRecentMenu(ui->menuOpen_recent); + CDUtils::CDCore::instance()->initPult(); + widgetK->setType(CDUtils::CDType::cdK); + widgetX->setType(CDUtils::CDType::cdX); + editFileK->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + editFileX->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + editFileC->setValue(QVariant::fromValue(QAD::File("", "*.dat"))); + log_icons[CDViewWidget::OKIcon] = QIcon(":/icons/dialog-ok-apply.png"); + log_icons[CDViewWidget::FailIcon] = QIcon(":/icons/dialog-cancel.png"); + log_icons[CDViewWidget::WaitIcon] = QIcon(":/icons/timer.png"); + setRecentMenu(menuOpen_recent); ribbon = new Ribbon(this); session.setFile("session_cdpult.conf"); session.addEntry(this); session.addEntry(ribbon->tabWidget()); session.load(); reset(); - connect(ui->viewK, SIGNAL(KSendSucceed()), this, SLOT(KSended())); - connect(ui->viewK, SIGNAL(KReceiveSucceed()), this, SLOT(KReceived())); - connect(ui->viewK, SIGNAL(KSendFailed()), this, SLOT(KSendFailed())); - connect(ui->viewK, SIGNAL(KReceiveFailed()), this, SLOT(KReceiveFailed())); + connect(widgetK, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); + connect(widgetX, SIGNAL(addToLog(CDViewWidget::LogIcon,QString)), this, SLOT(addToLog(CDViewWidget::LogIcon,QString))); if (windowState() == Qt::WindowMinimized) setWindowState(Qt::WindowNoState); } CDPultWindow::~CDPultWindow() { - delete ui; } @@ -44,26 +46,6 @@ void CDPultWindow::loadFile(const QString & fp) { } -void CDPultWindow::KReceived() { - addToLog(OKIcon, "K received succesfull"); -} - - -void CDPultWindow::KSended() { - addToLog(OKIcon, "K sended succesfull"); -} - - -void CDPultWindow::KSendFailed() { - addToLog(FailIcon, "K NOT sended"); -} - - -void CDPultWindow::KReceiveFailed() { - addToLog(FailIcon, "K NOT received"); -} - - void CDPultWindow::closeEvent(QCloseEvent *e) { EMainWindow::closeEvent(e); if (!e->isAccepted()) @@ -76,29 +58,45 @@ void CDPultWindow::closeEvent(QCloseEvent *e) { void CDPultWindow::reset(bool full) { setWindowTitle(QString("CD Pult")); - ui->viewK->setKFile(""); -// ui->viewK->clearK(); - file_name.clear(); - ui->viewK->refresh(); + widgetK->reset(); setChanged(false); } bool CDPultWindow::load(const QString & path) { - ui->viewK->setKFile(path); - ui->viewK->loadK(); - QFileInfo fi(path); - setWindowTitle(QString("CD Pult - %1").arg(fi.baseName())); + QPIConfig conf(path, QIODevice::ReadOnly); + QAD::File f = editFileK->value().value(); + checkSyncFiles->setChecked(false); + editFileK->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_k").value(), f.filter))); + editFileX->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_x").value(), f.filter))); + editFileC->setValue(QVariant::fromValue(QAD::File(conf.getValue("file_c").value(), f.filter))); + checkSyncFiles->setChecked(conf.getValue("sync_files")); + lineSessionName->setText(conf.getValue("session_name")); + checkHasK->setChecked(conf.getValue("has_k")); + checkHasX->setChecked(conf.getValue("has_x")); + checkHasC->setChecked(conf.getValue("has_c")); + setChanged(false); + file_name = path; return true; } bool CDPultWindow::save(const QString & path) { - ui->viewK->setKFile(path); - ui->viewK->saveK(); - QFileInfo fi(path); - setWindowTitle(QString("CD Pult - %1").arg(fi.baseName())); + QPIConfig conf(path, QIODevice::ReadWrite); + conf.clear(); + conf.setValue("file_k", editFileK->value().value().file); + conf.setValue("file_x", editFileX->value().value().file); + conf.setValue("file_c", editFileC->value().value().file); + conf.setValue("sync_files", checkSyncFiles->isChecked()); + conf.setValue("session_name", lineSessionName->text()); + conf.setValue("has_k", checkHasK->isChecked()); + conf.setValue("has_x", checkHasX->isChecked()); + conf.setValue("has_c", checkHasC->isChecked()); + file_name = path; return true; + + //widgetK->setFile(path); + //widgetK->save(); } @@ -112,42 +110,56 @@ void CDPultWindow::savingSession(QPIConfig & conf) { } -void CDPultWindow::addToLog(LogIcon icon, const QString & msg) { +void CDPultWindow::addToLog(CDViewWidget::LogIcon icon, const QString & msg) { QListWidgetItem * ni = new QListWidgetItem(log_icons[icon], "(" + QTime::currentTime().toString() + ") " + msg); - bool s = ui->listLog->verticalScrollBar()->value() == ui->listLog->verticalScrollBar()->maximum(); - ui->listLog->addItem(ni); - if (s) ui->listLog->scrollToBottom(); + bool s = listLog->verticalScrollBar()->value() == listLog->verticalScrollBar()->maximum(); + listLog->addItem(ni); + if (s) listLog->scrollToBottom(); } -void CDPultWindow::on_actionSend_K_triggered() { - if (K.inProgress()) {addToLog(WaitIcon, "processing..."); return;} - addToLog(WaitIcon, "Sending K..."); - ui->viewK->sendK(); -} - - -void CDPultWindow::on_actionReceive_K_triggered() { - if (K.inProgress()) {addToLog(WaitIcon, "processing..."); return;} - addToLog(WaitIcon, "Receiving K..."); - ui->viewK->receiveK(); -} - - -void CDPultWindow::on_actionParse_triggered() { - QString path = QFileDialog::getOpenFileName(this, "Select header file", "", "K Description(k_description.h);;Headers(*.h)"); - if (path.isEmpty()) return; - CDUtils::UpdateModeFlags mode = CDUtils::SaveByName; - if (!K.root().isEmpty()) { - QCDModeDialog cdm; - if (cdm.exec() != QDialog::Accepted) return; - mode = cdm.mode(); +void CDPultWindow::on_editFileK_valueChanged(const QVariant & p) { + if (!checkSyncFiles->isChecked()) return; + QFileInfo fi(p.value().file); + if (fi.path().isEmpty()) return; + QString n = fi.baseName(); + QString xn(n), cn(n); + if (n.contains("k")) { + xn.replace(n.indexOf("k"), 1, "x"); + cn.replace(n.indexOf("k"), 1, "c"); + } else { + xn += "_x"; + cn += "_c"; } - ui->viewK->buildFromHeader(path, mode); + QString ext = fi.suffix(), dot, dir; + QString kfn(fi.filePath()); + if (!ext.isEmpty()) { + kfn.chop(ext.size()); + if (kfn.endsWith(".")) { + kfn.chop(1); + dot = "."; + } + } + if (!fi.path().isEmpty() && fi.path() != ".") { + dir = fi.path(); + if (!dir.endsWith("/")) + dir += "/"; + } + QAD::File f = editFileK->value().value(); + f.file = dir + xn + dot + ext; editFileX->setValue(QVariant::fromValue(f)); + f.file = dir + cn + dot + ext; editFileC->setValue(QVariant::fromValue(f)); } -void CDPultWindow::on_actionCalculate_K_triggered() { - ui->viewK->calculateK(); - ui->viewK->refresh(); +void CDPultWindow::on_buttonSessionApply_clicked() { + widgetK->setFile(editFileK->value().value().file); + widgetX->setFile(editFileX->value().value().file); + dockCDKView->setVisible(checkHasK->isChecked()); + dockCDXView->setVisible(checkHasX->isChecked()); + //dockCDCView->setVisible(checkHasC->isChecked()); +} + + +void CDPultWindow::on_lineSessionName_textChanged(const QString & t) { + setWindowTitle(QString("CD Pult - %1").arg(t)); } diff --git a/qcd_utils/pult/cdpultwindow.h b/qcd_utils/pult/cdpultwindow.h index 2fc5f10..69850ab 100644 --- a/qcd_utils/pult/cdpultwindow.h +++ b/qcd_utils/pult/cdpultwindow.h @@ -2,20 +2,17 @@ #define CDPULTWINDOW_H #include "emainwindow.h" +#include "ui_cdpultwindow.h" +#include "cdviewwidget.h" #include "ribbon.h" #include "piobject.h" -namespace Ui { -class CDPultWindow; -} - -class CDPultWindow : public EMainWindow +class CDPultWindow : public EMainWindow, public Ui::CDPultWindow { Q_OBJECT Q_ENUMS(LogIcon) public: - enum LogIcon {NoIcon, OKIcon, FailIcon, WaitIcon}; explicit CDPultWindow(QWidget *parent = 0); ~CDPultWindow(); @@ -27,26 +24,20 @@ private: void reset(bool full = false); bool load(const QString & path); bool save(const QString & path); - QString loadFilter() {return "CD file(*.dat)";} - QString saveFilter() {return "CD file(*.dat)";} + QString loadFilter() {return "Pult session(*.conf)";} + QString saveFilter() {return loadFilter();} void loadingSession(QPIConfig & conf); void savingSession(QPIConfig & conf); - Ui::CDPultWindow *ui; Ribbon * ribbon; - QMap log_icons; + QMap log_icons; private slots: - void KSended(); - void KReceived(); - void KSendFailed(); - void KReceiveFailed(); - void addToLog(LogIcon icon, const QString & msg); - void on_actionSend_K_triggered(); - void on_actionReceive_K_triggered(); - void on_actionParse_triggered(); - void on_actionCalculate_K_triggered(); + void addToLog(CDViewWidget::LogIcon icon, const QString & msg); + void on_editFileK_valueChanged(const QVariant & p); + void on_buttonSessionApply_clicked(); + void on_lineSessionName_textChanged(const QString & t); }; #endif // CDPULTWINDOW_H diff --git a/qcd_utils/pult/cdpultwindow.ui b/qcd_utils/pult/cdpultwindow.ui index 0136f22..666d73a 100644 --- a/qcd_utils/pult/cdpultwindow.ui +++ b/qcd_utils/pult/cdpultwindow.ui @@ -6,8 +6,8 @@ 0 0 - 800 - 600 + 798 + 593 @@ -19,22 +19,14 @@ QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks|QMainWindow::VerticalTabs - - - - 0 - 0 - - - - + 0 0 - 800 - 21 + 798 + 24 @@ -79,20 +71,8 @@ 0 - - 0 - - - 0 - - - 0 - - - 0 - - + @@ -106,7 +86,7 @@ Log - 4 + 8 @@ -153,6 +133,184 @@ + + + + :/icons/qvariantedit.png:/icons/qvariantedit.png + + + X + + + 1 + + + + + + + + + + + + + :/icons/configure.png:/icons/configure.png + + + Session + + + 2 + + + + + + + + + Load ... + + + + :/icons/document-open-recent.png:/icons/document-open-recent.png + + + + + + + Save ... + + + + :/icons/document-save.png:/icons/document-save.png + + + + + + + Save as ... + + + + :/icons/document-save-as.png:/icons/document-save-as.png + + + + + + + + + Apply + + + + :/icons/dialog-ok-apply.png:/icons/dialog-ok-apply.png + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Name: + + + + + + + + + + K file: + + + + + + + + + + X file: + + + + + + + + + + C file: + + + + + + + + + + Sync files + + + + + + + + + K + + + + + + + X + + + + + + + C + + + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + @@ -167,7 +325,7 @@ - + :/icons/document-save.png:/icons/document-save.png @@ -245,10 +403,7 @@ - - - - + @@ -271,6 +426,16 @@
emainwindow.h
1 + + CLineEdit + QLineEdit +
clineedit.h
+
+ + QVariantEdit + QWidget +
qvariantedit.h
+
EDockWidget QDockWidget @@ -278,16 +443,16 @@ 1 - CDKView - QTreeView -
qcd_kview.h
+ CDViewWidget + QWidget +
cdviewwidget.h
+ 1
- - + @@ -339,5 +504,85 @@ + + checkSyncFiles + toggled(bool) + editFileX + setDisabled(bool) + + + 786 + 227 + + + 786 + 179 + + + + + checkSyncFiles + toggled(bool) + editFileC + setDisabled(bool) + + + 786 + 227 + + + 786 + 200 + + + + + buttonSessionLoad + clicked() + CDPultWindow + openFile() + + + 589 + 68 + + + 803 + 62 + + + + + buttonSessionSave + clicked() + CDPultWindow + saveFile() + + + 671 + 70 + + + 806 + 48 + + + + + buttonSessionSaveAs + clicked() + CDPultWindow + saveAsFile() + + + 754 + 66 + + + 805 + 106 + + + diff --git a/qcd_utils/pult/cdviewwidget.cpp b/qcd_utils/pult/cdviewwidget.cpp new file mode 100644 index 0000000..a01c87a --- /dev/null +++ b/qcd_utils/pult/cdviewwidget.cpp @@ -0,0 +1,78 @@ +#include "cdviewwidget.h" +#include "cdutils_core.h" +#include "qcd_core.h" +#include "qcd_model.h" +#include "qcd_modedialog.h" +#include "qvariantedit.h" +#include + + +CDViewWidget::CDViewWidget(QWidget * parent) : QWidget(parent), Ui::CDViewWidget() { + qRegisterMetaType("CDViewWidget::LogIcon"); + setupUi(this); + connect(view, SIGNAL(sendSucceed()), this, SLOT(sended())); + connect(view, SIGNAL(receiveSucceed()), this, SLOT(received())); + connect(view, SIGNAL(sendFailed()), this, SLOT(sendFailed())); + connect(view, SIGNAL(receiveFailed()), this, SLOT(receiveFailed())); +} + + +CDViewWidget::~CDViewWidget() { +} + + +void CDViewWidget::reset() { + setFile(""); +} + + +void CDViewWidget::setType(int t) { + view->setType((CDUtils::CDType::cdT)t); + tl_u = view->typeLetter().toUpper(); + tl_l = view->typeLetter().toLower(); + view->refresh(); +} + + +void CDViewWidget::setFile(const QString & f) { + view->setFile(f); + view->load(); +} + + +void CDViewWidget::on_buttonSend_clicked() { + if (view->inProgress()) {addToLog(WaitIcon, "processing..."); return;} + addToLog(WaitIcon, "Sending " + tl_u + "..."); + view->send(); +} + + +void CDViewWidget::on_buttonReceive_clicked() { + if (view->inProgress()) {addToLog(WaitIcon, "processing..."); return;} + addToLog(WaitIcon, "Receiving " + tl_u + "..."); + view->receive(); +} + + +void CDViewWidget::on_buttonLoad_clicked() { + view->load(); +} + + +void CDViewWidget::on_buttonSave_clicked() { + view->save(); +} + + +void CDViewWidget::on_buttonParse_clicked() { + QString path = QFileDialog::getOpenFileName(this, "Select header file", "", + QString("%1 Description(%2_description.h);;Headers(*.h)").arg(tl_u, tl_l)); + if (path.isEmpty()) return; + CDUtils::UpdateModeFlags mode = CDUtils::SaveByName; + if (!view->root()->isEmpty()) { + QCDModeDialog cdm; + if (cdm.exec() != QDialog::Accepted) return; + mode = cdm.mode(); + } + view->buildFromHeader(path, mode); +} diff --git a/qcd_utils/pult/cdviewwidget.h b/qcd_utils/pult/cdviewwidget.h new file mode 100644 index 0000000..3145666 --- /dev/null +++ b/qcd_utils/pult/cdviewwidget.h @@ -0,0 +1,41 @@ +#ifndef CDVIEWWIDGET_H +#define CDVIEWWIDGET_H + +#include +#include "ui_cdviewwidget.h" + + +class CDViewWidget : public QWidget, public Ui::CDViewWidget +{ + Q_OBJECT +public: + explicit CDViewWidget(QWidget *parent = 0); + ~CDViewWidget(); + + enum LogIcon {NoIcon, OKIcon, FailIcon, WaitIcon}; + + void reset(); + void setType(int t); + void setFile(const QString & f); + +private: + QString tl_u, tl_l; + +private slots: + void sended() {addToLog(OKIcon, tl_u + " " + tr("sended succesfull"));} + void received() {addToLog(OKIcon, tl_u + " " + tr("received succesfull"));} + void sendFailed() {addToLog(FailIcon, tl_u + " " + tr("NOT sended"));} + void receiveFailed() {addToLog(FailIcon, tl_u + " " + tr("NOT received"));} + void on_buttonSend_clicked(); + void on_buttonReceive_clicked(); + void on_buttonLoad_clicked(); + void on_buttonSave_clicked(); + void on_buttonParse_clicked(); + //void on_buttonCalculate_clicked(); + +signals: + void addToLog(CDViewWidget::LogIcon icon, const QString & msg); + +}; + +#endif // CDVIEWWIDGET_H diff --git a/qcd_utils/pult/cdviewwidget.ui b/qcd_utils/pult/cdviewwidget.ui new file mode 100644 index 0000000..9d01778 --- /dev/null +++ b/qcd_utils/pult/cdviewwidget.ui @@ -0,0 +1,121 @@ + + + CDViewWidget + + + + 0 + 0 + 689 + 459 + + + + CD Pult + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + Save + + + + :/icons/document-save.png:/icons/document-save.png + + + + + + + Load + + + + :/icons/document-open.png:/icons/document-open.png + + + + + + + Receive + + + + :/icons/document-revert.png:/icons/document-revert.png + + + + + + + Update description ... + + + + :/icons/view-refresh.png:/icons/view-refresh.png + + + + + + + Send + + + + :/icons/flame.png:/icons/flame.png + + + + + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + + + + + + CDView + QTreeView +
qcd_view.h
+
+
+ + + + +
diff --git a/qcd_utils/pult/icons/document-revert.png b/qcd_utils/pult/icons/document-revert.png new file mode 100644 index 0000000000000000000000000000000000000000..e04514beb024f602bee551572590553e118e613a GIT binary patch literal 2885 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 #include #include -#include +#include using namespace CDUtils; @@ -115,7 +115,7 @@ bool QCDCore::bindWidget(QWidget * w) { if (!w) return false; QString on = w->objectName(); QString cn = w->metaObject()->className(); - if (cn == "CDKView") { + if (cn == "CDView") { bindView(w); return false; } @@ -148,7 +148,7 @@ bool QCDCore::bindWidget(QWidget * w, const CDType k) { connect(w, SIGNAL(textChanged(QString)), this, SLOT(slotText(QString)), Qt::UniqueConnection); ok = true; } - if (cn == "CDKView") { + if (cn == "CDView") { bindView(w); } if (!ok) return false; @@ -180,7 +180,7 @@ void QCDCore::updateBindedWidgets() { void QCDCore::bindView(QWidget * v) { - CDKView * w = qobject_cast(v); + CDView * w = qobject_cast(v); if (!w) return; connect(this, SIGNAL(updateViewRequest()), w->model(), SLOT(updateModel()), Qt::UniqueConnection); } diff --git a/qcd_utils/qcd_kview.cpp b/qcd_utils/qcd_kview.cpp deleted file mode 100644 index 38a2fd9..0000000 --- a/qcd_utils/qcd_kview.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include "cdutils_k.h" -#include "qcd_kview.h" -#include "qcd_kmodel.h" -#include "piqt.h" -#include "pifile.h" - -using namespace CDUtils; - - -CDKView::CDKView(QWidget *parent) : QTreeView(parent) { - kmodel = 0; - CONNECTU(&K, sended, this, cdk_sendSucceed); - CONNECTU(&K, sendFailed, this, cdk_sendFailed); - CONNECTU(&K, received, this, cdk_receiveSucceed); - CONNECTU(&K, receiveFailed, this, cdk_receiveFailed); - connect(this, SIGNAL(_qcdk_sendFailed()), this, SLOT(k_sendFailed()), Qt::QueuedConnection); - connect(this, SIGNAL(_qcdk_sendSucceed()), this, SLOT(k_sendSucceed()), Qt::QueuedConnection); - connect(this, SIGNAL(_qcdk_receiveFailed()), this, SLOT(k_receiveFailed()), Qt::QueuedConnection); - connect(this, SIGNAL(_qcdk_receiveSucceed()), this, SLOT(k_receiveSucceed()), Qt::QueuedConnection); -} - - -CDKView::~CDKView() { - if (kmodel) delete kmodel; - kmodel = 0; -} - - -void CDKView::refresh() { - if (!kmodel) { - kmodel = new CDKItemModel(); - setModel(kmodel); - setItemDelegateForColumn(4, new CDKDelegate()); - } - kmodel->rebuildModel(); - expandAll(); - for (int i=0; i<6; i++) resizeColumnToContents(i); -} - - -void CDKView::setKFile(const QString &filename) { - K.setFileName(Q2PIString(filename)); -} - - -void CDKView::startPing() { - K.startPing(); -} - - -void CDKView::sendK() { - busyStatusChanged(true); - K.send(); -} - - -void CDKView::receiveK() { - busyStatusChanged(true); - K.request(); -} - - -void CDKView::saveK() { - K.writeFile(); -} - - -void CDKView::loadK() { - K.readFile(); - K.calculate(); - refresh(); -} - - -void CDKView::clearK() { - //piCout << "clearK"; - K.root() = CDSection(); - refresh(); -} - - -void CDKView::buildFromHeader(const QString &kdescription, int mode) { - if (kdescription.isEmpty()) return; - PIString kdesc_file = Q2PIString(QDir::current().relativeFilePath(kdescription)); - PIFile f(kdesc_file, PIIODevice::ReadOnly); - K.update(&f, mode); - refresh(); -} - - -void CDKView::calculateK() { - K.calculate(); -} - - -void CDKView::k_sendFailed() { - busyStatusChanged(false); - emit messageStatus("send failed"); - emit KSendFailed(); -} - - -void CDKView::k_sendSucceed() { - busyStatusChanged(false); - emit messageStatus("send success"); - emit KSendSucceed(); -} - - -void CDKView::k_receiveFailed() { - busyStatusChanged(false); - emit messageStatus("receive failed"); - emit KReceiveFailed(); -} - - -void CDKView::k_receiveSucceed() { - busyStatusChanged(false); - emit messageStatus("receive success"); - refresh(); - emit KReceiveSucceed(); -} - diff --git a/qcd_utils/qcd_kview.h b/qcd_utils/qcd_kview.h deleted file mode 100644 index 2c3025c..0000000 --- a/qcd_utils/qcd_kview.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QCD_KVIEW_H -#define QCD_KVIEW_H - -#include "piobject.h" -#include - -class CDKItemModel; - -class CDKView: public QTreeView, public PIObject -{ - Q_OBJECT - PIOBJECT(CDKView) -public: - explicit CDKView(QWidget *parent = 0); - ~CDKView(); - - void setKFile(const QString & filename); - void startPing(); - - CDKItemModel * CDKModel() {return kmodel;} - -public slots: - void refresh(); - void sendK(); - void receiveK(); - void saveK(); - void loadK(); - void clearK(); - void buildFromHeader(const QString & kdescription, int mode = 2); - void calculateK(); - -private slots: - void k_sendFailed(); - void k_sendSucceed(); - void k_receiveFailed(); - void k_receiveSucceed(); - -private: - EVENT_HANDLER(void, cdk_sendFailed) {emit _qcdk_sendFailed();} - EVENT_HANDLER(void, cdk_sendSucceed) {emit _qcdk_sendSucceed();} - EVENT_HANDLER(void, cdk_receiveFailed) {emit _qcdk_receiveFailed();} - EVENT_HANDLER(void, cdk_receiveSucceed) {emit _qcdk_receiveSucceed();} - - CDKItemModel * kmodel; - -signals: - void KSendFailed(); - void KSendSucceed(); - void KReceiveFailed(); - void KReceiveSucceed(); - void messageStatus(QString msg); - void busyStatusChanged(bool busy); - - void _qcdk_sendFailed(); // PRIVATE - void _qcdk_sendSucceed(); // PRIVATE - void _qcdk_receiveFailed(); // PRIVATE - void _qcdk_receiveSucceed(); // PRIVATE - -}; - -#endif // QCD_KVIEW_H diff --git a/qcd_utils/qcd_kmodel.cpp b/qcd_utils/qcd_model.cpp similarity index 51% rename from qcd_utils/qcd_kmodel.cpp rename to qcd_utils/qcd_model.cpp index 7239cd1..5ead0a2 100644 --- a/qcd_utils/qcd_kmodel.cpp +++ b/qcd_utils/qcd_model.cpp @@ -1,5 +1,6 @@ -#include "qcd_kmodel.h" -#include "cdutils_k.h" +#include "qcd_model.h" +#include "cdutils_interface.h" +#include "cdutils_core.h" #include "piqt.h" #include #include @@ -11,173 +12,26 @@ using namespace CDUtils; -CDKItemModel::CDKItemModel(QObject *parent) : QAbstractItemModel(parent) { - root = 0; - internalRebuild(); -} - - -CDKItemModel::~CDKItemModel() { - delete root; -} - - -QVariant CDKItemModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) return QVariant(); - CDKItem *item = getItem(index); - return item->data(index.column(), role); -} - - -QVariant CDKItemModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { - switch (section) { - case 0: return trUtf8("Index"); - case 1: return trUtf8("Name"); - case 2: return trUtf8("Type"); - case 3: return trUtf8("Expression"); - case 4: return trUtf8("Value"); - case 5: return trUtf8("Comment"); - } - } - return QVariant(); -} - - -QModelIndex CDKItemModel::index(int row, int column, const QModelIndex &parent) const { - if (parent.isValid() && parent.column() != 0) return QModelIndex(); - CDKItem * p = getItem(parent); - CDKItem * c = p->childs.value(row, 0); - if (c) return createIndex(row, column, c); - else return QModelIndex(); -} - - -QModelIndex CDKItemModel::parent(const QModelIndex &index) const { - if (!index.isValid()) return QModelIndex(); - CDKItem * c = getItem(index); - CDKItem * p = c->parent_; - if (p == root) return QModelIndex(); - return createIndex(p->parent_->childs.indexOf(p), 0, p); -} - - -int CDKItemModel::rowCount(const QModelIndex &parent) const { - CDKItem *p = getItem(parent); - return p->childs.count(); -} - - -int CDKItemModel::columnCount(const QModelIndex &parent) const { - return 6; -} - - -Qt::ItemFlags CDKItemModel::flags(const QModelIndex & index) const { - if (!index.isValid()) return 0; - Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - CDKItem * item = getItem(index); - if ((index.column() == 3 || index.column() == 4) && item->type_ == CDKItem::ItemCDType) f |= Qt::ItemIsEditable; - if (item->type_ == CDKItem::ItemCDType && index.column() == 4) { - CDType t = K.section(item->buildPath())[item->index_]; - if (t.type() == "b") { - f |= Qt::ItemIsUserCheckable; -// piCout << "ItemIsUserCheckable"; - } - } - return f; -} - - -bool CDKItemModel::setData(const QModelIndex & index, const QVariant &value, int role) { - if (role == Qt::CheckStateRole && index.column() == 4) { - CDKItem * item = getItem(index); - if (item->type_ == CDKItem::ItemCDType) { - CDType t = K.section(item->buildPath())[item->index_]; - if (t.type() == "b") { - bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); - QModelIndex rin(CDKItemModel::index(index.row(), 3, index.parent())); - emit dataChanged(rin, rin); - return result; - } - } - } - if (role != Qt::EditRole) return false; - CDKItem * item = getItem(index); - bool result = item->setData(index.column(), value); - if (result) { - QModelIndex rin(CDKItemModel::index(index.row(), 3, index.parent())); - emit dataChanged(rin, rin); - emit dataChanged(index, index); - } - return result; -} - - -void CDKItemModel::rebuildModel() { - beginResetModel(); - internalRebuild(); - endResetModel(); -} - - -void CDKItemModel::buildItem(CDKItem *it, CDSection & r) { - //piCout << "build item" << r.name << r.alias; - PIMap::iterator i; - for (i = r.cd.begin(); i != r.cd.end(); ++i) { - it->childs << new CDKItem(i.key(), CDKItem::ItemCDType, it); - } - PIMap::iterator j; - for (j = r.s.begin(); j != r.s.end(); ++j) { - it->childs << new CDKItem(j.key(), CDKItem::ItemCDSection, it); - buildItem(it->childs.back(), j.value()); - } -} - - -void CDKItemModel::updateModel() { - beginResetModel(); - endResetModel(); -} - - -void CDKItemModel::internalRebuild() { - //qDebug() << "[CDKItemModel]" << "internalRebuild()"; - if (root) delete root; - root = new CDKItem(0, CDKItem::ItemCDSection, 0); - CDSection & r = K.root(); - buildItem(root, r); -} - - -CDKItem * CDKItemModel::getItem(const QModelIndex &index) const { - if (index.isValid()) { - CDKItem * item = static_cast(index.internalPointer()); - if (item) return item; - } - return root; -} - - // CDKItem -CDKItem::CDKItem(int index, CDKItem::CDKItemType type, CDKItem *parent) { +CDItem::CDItem(CDUtils::Interface * i, int index, CDItem::CDItemType type, CDItem *parent) { + interface = i; index_ = index; parent_ = parent; type_ = type; } -CDKItem::~CDKItem() { +CDItem::~CDItem() { qDeleteAll(childs); } -QVariant CDKItem::data(int column, int role) const { +QVariant CDItem::data(int column, int role) const { if (role == Qt::BackgroundRole) { switch (type_) { case ItemCDType: { - CDType & t = K.section(buildPath())[index_]; + CDType & t = interface->section(buildPath())[index_]; if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230)); else return QBrush(QColor(255, 128, 128)); } @@ -185,29 +39,28 @@ QVariant CDKItem::data(int column, int role) const { } } if (role == Qt::CheckStateRole && type_ == ItemCDType && column == 4) { - CDType & t = K.section(buildPath())[index_]; + CDType & t = interface->section(buildPath())[index_]; if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked; else QVariant(); } if (role == Qt::ToolTipRole && type_ == ItemCDType) { - CDType & t = K.section(buildPath())[index_]; + CDType & t = interface->section(buildPath())[index_]; return PI2QString(t.errorString()); } if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); PIDeque path = buildPath(); - CDSection & rs = K.section(path); + CDSection & rs = interface->section(path); CDSection s; switch (type_) { case ItemCDType: switch (column) { - case 0: return QString::number(index_); - case 1: return PI2QString(rs[index_].name()); - case 2: return stringType(rs[index_].type()); - case 3: return PI2QString(rs[index_].formula()); - case 4: return value(rs[index_], role); - case 5: return PI2QString(rs[index_].comment()); - default: - break; + case 0: return QString::number(index_); + case 1: return PI2QString(rs[index_].name()); + case 2: return stringType(rs[index_].type()); + case 3: return PI2QString(rs[index_].formula()); + case 4: return value(rs[index_], role); + case 5: return PI2QString(rs[index_].comment()); + default: break; } break; case ItemCDSection: @@ -215,10 +68,9 @@ QVariant CDKItem::data(int column, int role) const { // piCout << rs.name << rs.alias << s.name << s.alias; switch (column) { case 0: return QString("[") + QString::number(index_) + QString("]"); - case 1: return PI2QString(s.alias); - case 2: return PI2QString(s.name); - default: - break; + case 1: return PI2QString(s.alias); + case 2: return PI2QString(s.name); + default: break; } break; } @@ -226,7 +78,7 @@ QVariant CDKItem::data(int column, int role) const { } -QVariant CDKItem::value(CDType t, int role) const { +QVariant CDItem::value(CDType t, int role) const { if (t.type() == "f") return t.toDouble(); if (t.type() == "n") return t.toInt(); if (t.type() == "b") return t.toBool(); @@ -240,19 +92,19 @@ QVariant CDKItem::value(CDType t, int role) const { } -bool CDKItem::setData(int column, const QVariant &value) { +bool CDItem::setData(int column, const QVariant &value) { if ((column == 3 || column == 4) && type_ == ItemCDType) { - K.section(buildPath())[index_].setValue(Q2PIString(value.toString())); - K.calculate(); + interface->section(buildPath())[index_].setValue(Q2PIString(value.toString())); + interface->calculate(); return true; } return false; } -PIDeque CDKItem::buildPath() const { +PIDeque CDItem::buildPath() const { PIDeque path; - CDKItem * p = parent_; + CDItem * p = parent_; while (p) { path.push_front(p->index_); p = p->parent_; @@ -262,7 +114,7 @@ PIDeque CDKItem::buildPath() const { } -QString CDKItem::stringType(const PIString & t) const { +QString CDItem::stringType(const PIString & t) const { QString n = PI2QString(t); if (n.isEmpty()) return QString(""); switch (n[0].toLatin1()) { @@ -286,22 +138,22 @@ QString CDKItem::stringType(const PIString & t) const { // CDKDelegate -CDKDelegate::CDKDelegate(QObject *parent) : QStyledItemDelegate(parent) { +CDDelegate::CDDelegate(QObject *parent) : QStyledItemDelegate(parent) { } -QWidget *CDKDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { +QWidget *CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { return new QVariantEdit(parent); } -void CDKDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { +void CDDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariantEdit *edit = static_cast(editor); edit->setValue(index.model()->data(index, Qt::EditRole)); } -void CDKDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { +void CDDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QVariantEdit *edit = static_cast(editor); QVariant v = edit->value(); if (v.canConvert()) { @@ -311,13 +163,169 @@ void CDKDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const } -void CDKDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { +void CDDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); } -QSize CDKDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { +QSize CDDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QSize s = QStyledItemDelegate::sizeHint(option, index); s.setWidth(s.width() + 20); return s; } + + +// CDItemModel + +CDItemModel::CDItemModel(int type_, QObject *parent) : QAbstractItemModel(parent) { + interface = new Interface((CDType::cdT)type_); + root = 0; + internalRebuild(); +} + + +CDItemModel::~CDItemModel() { + delete root; + delete interface; +} + + +QVariant CDItemModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + CDItem *item = getItem(index); + return item->data(index.column(), role); +} + + +QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case 0: return trUtf8("Index"); + case 1: return trUtf8("Name"); + case 2: return trUtf8("Type"); + case 3: return trUtf8("Expression"); + case 4: return trUtf8("Value"); + case 5: return trUtf8("Comment"); + } + } + return QVariant(); +} + + +QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const { + if (parent.isValid() && parent.column() != 0) return QModelIndex(); + CDItem * p = getItem(parent); + CDItem * c = p->childs.value(row, 0); + if (c) return createIndex(row, column, c); + else return QModelIndex(); +} + + +QModelIndex CDItemModel::parent(const QModelIndex &index) const { + if (!index.isValid()) return QModelIndex(); + CDItem * c = getItem(index); + CDItem * p = c->parent_; + if (p == root) return QModelIndex(); + return createIndex(p->parent_->childs.indexOf(p), 0, p); +} + + +int CDItemModel::rowCount(const QModelIndex &parent) const { + CDItem *p = getItem(parent); + return p->childs.count(); +} + + +int CDItemModel::columnCount(const QModelIndex &parent) const { + return 6; +} + + +Qt::ItemFlags CDItemModel::flags(const QModelIndex & index) const { + if (!index.isValid()) return 0; + Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + CDItem * item = getItem(index); + if (!item) return 0; + CDType & t(interface->section(item->buildPath())[item->index_]); + if ((index.column() == 3 || index.column() == 4) && + (item->type_ == CDItem::ItemCDType) && + (t.cd_type() == CDType::cdK)) + f |= Qt::ItemIsEditable; + if (item->type_ == CDItem::ItemCDType && index.column() == 4) { + if (t.type() == "b") { + f |= Qt::ItemIsUserCheckable; +// piCout << "ItemIsUserCheckable"; + } + } + return f; +} + + +bool CDItemModel::setData(const QModelIndex & index, const QVariant &value, int role) { + if (role == Qt::CheckStateRole && index.column() == 4) { + CDItem * item = getItem(index); + if (item->type_ == CDItem::ItemCDType) { + CDType t = interface->section(item->buildPath())[item->index_]; + if (t.type() == "b") { + bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); + QModelIndex rin(CDItemModel::index(index.row(), 3, index.parent())); + emit dataChanged(rin, rin); + return result; + } + } + } + if (role != Qt::EditRole) return false; + CDItem * item = getItem(index); + bool result = item->setData(index.column(), value); + if (result) { + QModelIndex rin(CDItemModel::index(index.row(), 3, index.parent())); + emit dataChanged(rin, rin); + emit dataChanged(index, index); + } + return result; +} + + +void CDItemModel::rebuildModel() { + beginResetModel(); + internalRebuild(); + endResetModel(); +} + + +void CDItemModel::buildItem(CDItem *it, CDSection & r) { + //piCout << "build item" << r.name << r.alias; + PIMap::iterator i; + for (i = r.cd.begin(); i != r.cd.end(); ++i) { + it->childs << new CDItem(interface, i.key(), CDItem::ItemCDType, it); + } + PIMap::iterator j; + for (j = r.s.begin(); j != r.s.end(); ++j) { + it->childs << new CDItem(interface, j.key(), CDItem::ItemCDSection, it); + buildItem(it->childs.back(), j.value()); + } +} + + +void CDItemModel::updateModel() { + beginResetModel(); + endResetModel(); +} + + +void CDItemModel::internalRebuild() { + //qDebug() << "[CDKItemModel]" << "internalRebuild()"; + if (root) delete root; + root = new CDItem(interface, 0, CDItem::ItemCDSection, 0); + CDSection & r = interface->root(); + buildItem(root, r); +} + + +CDItem * CDItemModel::getItem(const QModelIndex &index) const { + if (index.isValid()) { + CDItem * item = static_cast(index.internalPointer()); + if (item) return item; + } + return root; +} diff --git a/qcd_utils/qcd_kmodel.h b/qcd_utils/qcd_model.h similarity index 60% rename from qcd_utils/qcd_kmodel.h rename to qcd_utils/qcd_model.h index f77a89d..75a3357 100644 --- a/qcd_utils/qcd_kmodel.h +++ b/qcd_utils/qcd_model.h @@ -1,5 +1,5 @@ -#ifndef QCD_KMODEL_H -#define QCD_KMODEL_H +#ifndef QCD_MODEL_H +#define QCD_MODEL_H #include #include @@ -7,20 +7,24 @@ #include "pistring.h" namespace CDUtils { -class CDSection; -class CDType; + class CDType; + class CDSection; + class Interface; } -namespace QAD { -struct Enum; -} -class CDKItemModel; -class CDKItem { - friend class CDKItemModel; +namespace QAD { + struct Enum; +} + +class CDItemModel; + + +class CDItem { + friend class CDItemModel; public: - enum CDKItemType{ItemCDType, ItemCDSection}; - CDKItem(int index, CDKItemType type, CDKItem * parent); - ~CDKItem(); + enum CDItemType{ItemCDType, ItemCDSection}; + CDItem(CDUtils::Interface * interface, int index, CDItemType type, CDItem * parent); + ~CDItem(); QVariant data(int column, int role) const; QVariant value(CDUtils::CDType t, int role) const; bool setData(int column, const QVariant & value); @@ -29,20 +33,21 @@ private: PIDeque buildPath() const; QString stringType(const PIString & t) const; - CDKItem * parent_; + CDUtils::Interface * interface; + CDItem * parent_; int index_; - CDKItemType type_; - QList childs; + CDItemType type_; + QList childs; }; -class CDKDelegate : public QStyledItemDelegate +class CDDelegate : public QStyledItemDelegate { Q_OBJECT public: - CDKDelegate(QObject *parent = 0); + CDDelegate(QObject *parent = 0); - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; @@ -50,11 +55,11 @@ public: }; -class CDKItemModel : public QAbstractItemModel { +class CDItemModel : public QAbstractItemModel { Q_OBJECT public: - explicit CDKItemModel(QObject *parent = 0); - ~CDKItemModel(); + explicit CDItemModel(int type_, QObject *parent = 0); + ~CDItemModel(); QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; @@ -65,7 +70,7 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - void buildItem(CDKItem * it, CDUtils::CDSection &r); + void buildItem(CDItem * it, CDUtils::CDSection &r); public slots: void rebuildModel(); @@ -73,12 +78,13 @@ public slots: private: void internalRebuild(); - CDKItem * getItem(const QModelIndex & index) const; + CDItem * getItem(const QModelIndex & index) const; - CDKItem * root; + CDUtils::Interface * interface; + CDItem * root; signals: }; -#endif // QCD_KMODEL_H +#endif // QCD_MODEL_H diff --git a/qcd_utils/qcd_view.cpp b/qcd_utils/qcd_view.cpp new file mode 100644 index 0000000..cdc53a4 --- /dev/null +++ b/qcd_utils/qcd_view.cpp @@ -0,0 +1,214 @@ +#include +#include "cdutils_k.h" +#include "cdutils_x.h" +#include "cdutils_core.h" +#include "qcd_view.h" +#include "qcd_model.h" +#include "piqt.h" +#include "pifile.h" + +using namespace CDUtils; + + +CDView::CDView(QWidget *parent) : QTreeView(parent) { + type_ = -1; + model_ = 0; + connect(this, SIGNAL(_qcd_sendFailed()), this, SLOT(cd_sendFailed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_sendSucceed()), this, SLOT(cd_sendSucceed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_receiveFailed()), this, SLOT(cd_receiveFailed()), Qt::QueuedConnection); + connect(this, SIGNAL(_qcd_receiveSucceed()), this, SLOT(cd_receiveSucceed()), Qt::QueuedConnection); +} + + +CDView::~CDView() { + if (model_) delete model_; + model_ = 0; +} + + +void CDView::setType(int cdt) { + if (cdt < 0) return; + if (type_ >= 0) return; + type_ = cdt; + switch ((CDType::cdT)type_) { + case CDType::cdK: + CONNECTU(&K, sended, this, pi_cd_sendSucceed); + CONNECTU(&K, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&K, received, this, pi_cd_receiveSucceed); + CONNECTU(&K, receiveFailed, this, pi_cd_receiveFailed); + break; + case CDType::cdX: + CONNECTU(&X, sended, this, pi_cd_sendSucceed); + CONNECTU(&X, sendFailed, this, pi_cd_sendFailed); + CONNECTU(&X, received, this, pi_cd_receiveSucceed); + CONNECTU(&X, receiveFailed, this, pi_cd_receiveFailed); + break; + default: break; + } + +} + + +void CDView::refresh() { + if (type_ < 0) return; + if (!model_) { + model_ = new CDItemModel(type_); + setModel(model_); + setItemDelegateForColumn(4, new CDDelegate()); + } + model_->rebuildModel(); + switch ((CDType::cdT)type_) { + case CDType::cdX: + setColumnHidden(3, true); + break; + default: break; + } + expandAll(); + for (int i=0; i<6; i++) resizeColumnToContents(i); +} + + +void CDView::setFile(const QString & filename) { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.setFileName(Q2PIString(filename)); break; + case CDType::cdX: X.setFileName(Q2PIString(filename)); break; + default: break; + } +} + + +bool CDView::inProgress() const { + switch ((CDType::cdT)type_) { + case CDType::cdK: return K.inProgress(); break; + case CDType::cdX: return X.inProgress(); break; + default: break; + } + return false; +} + + +void CDView::startPing() { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.startPing(); break; + case CDType::cdX: X.startPing(); break; + default: break; + } +} + + +CDSection * CDView::root() { + return CDCore::instance()->root((CDType::cdT)type_); +} + + +QString CDView::typeLetter() const { + return PI2QString(CDCore::instance()->typeLetter((CDType::cdT)type_)); +} + + +void CDView::send() { + busyStatusChanged(true); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.send(); break; + case CDType::cdX: X.send(); break; + default: break; + } +} + + +void CDView::receive() { + busyStatusChanged(true); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.request(); break; + case CDType::cdX: X.request(); break; + default: break; + } +} + + +void CDView::save() { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.writeFile(); break; + case CDType::cdX: X.writeFile(); break; + default: break; + } +} + + +void CDView::load() { + switch ((CDType::cdT)type_) { + case CDType::cdK: + K.readFile(); + K.calculate(); + break; + case CDType::cdX: + X.readFile(); + X.calculate(); + break; + default: break; + } + refresh(); +} + + +void CDView::clear() { + //piCout << "clearK"; + switch ((CDType::cdT)type_) { + case CDType::cdK: K.root() = CDSection(); break; + case CDType::cdX: X.root() = CDSection(); break; + default: break; + } + refresh(); +} + + +void CDView::buildFromHeader(const QString & description, int mode) { + if (description.isEmpty()) return; + PIString desc_file = Q2PIString(QDir::current().relativeFilePath(description)); + PIFile f(desc_file, PIIODevice::ReadOnly); + switch ((CDType::cdT)type_) { + case CDType::cdK: K.update(&f, mode); break; + case CDType::cdX: X.update(&f, mode); break; + default: break; + } + refresh(); +} + + +void CDView::calculate() { + switch ((CDType::cdT)type_) { + case CDType::cdK: K.calculate(); break; + case CDType::cdX: X.calculate(); break; + default: break; + } +} + + +void CDView::cd_sendFailed() { + busyStatusChanged(false); + emit messageStatus("send failed"); + emit sendFailed(); +} + + +void CDView::cd_sendSucceed() { + busyStatusChanged(false); + emit messageStatus("send success"); + emit sendSucceed(); +} + + +void CDView::cd_receiveFailed() { + busyStatusChanged(false); + emit messageStatus("receive failed"); + emit receiveFailed(); +} + + +void CDView::cd_receiveSucceed() { + refresh(); + busyStatusChanged(false); + emit messageStatus("receive success"); + emit receiveSucceed(); +} + diff --git a/qcd_utils/qcd_view.h b/qcd_utils/qcd_view.h new file mode 100644 index 0000000..487da91 --- /dev/null +++ b/qcd_utils/qcd_view.h @@ -0,0 +1,71 @@ +#ifndef QCD_VIEW_H +#define QCD_VIEW_H + +#include "piobject.h" +#include + +namespace CDUtils { + class CDType; + class CDSection; +} + +class CDItemModel; + +class CDView: public QTreeView, public PIObject +{ + Q_OBJECT + PIOBJECT(CDView) +public: + explicit CDView(QWidget *parent = 0); + ~CDView(); + + void setType(int cdt); + void setFile(const QString & filename); + bool inProgress() const; + void startPing(); + CDUtils::CDSection * root(); + QString typeLetter() const; + + CDItemModel * CDModel() {return model_;} + +public slots: + void refresh(); + void send(); + void receive(); + void save(); + void load(); + void clear(); + void buildFromHeader(const QString & description, int mode = 2); + void calculate(); + +private slots: + void cd_sendFailed(); + void cd_sendSucceed(); + void cd_receiveFailed(); + void cd_receiveSucceed(); + +private: + EVENT_HANDLER(void, pi_cd_sendFailed) {emit _qcd_sendFailed();} + EVENT_HANDLER(void, pi_cd_sendSucceed) {emit _qcd_sendSucceed();} + EVENT_HANDLER(void, pi_cd_receiveFailed) {emit _qcd_receiveFailed();} + EVENT_HANDLER(void, pi_cd_receiveSucceed) {emit _qcd_receiveSucceed();} + + CDItemModel * model_; + int type_; + +signals: + void sendFailed(); + void sendSucceed(); + void receiveFailed(); + void receiveSucceed(); + void messageStatus(QString msg); + void busyStatusChanged(bool busy); + + void _qcd_sendFailed(); // PRIVATE + void _qcd_sendSucceed(); // PRIVATE + void _qcd_receiveFailed(); // PRIVATE + void _qcd_receiveSucceed(); // PRIVATE + +}; + +#endif // QCD_VIEW_H