void apply(int number, char op) { Operation newOperation(number, op); int i = opStack.size() - 1; while (i >= 0) { Operation next = opStack[i--]; if (Operators::rank(next.op) >= Operators::rank(op)) { newOperation.number = next.apply(newOperation.number); opStack.pop_back(); } else { break; } } opStack.push_back(newOperation); }
bool CBooleanLogicOperation::Deserialize(const TiXmlNode *node) { if (node == NULL) return false; // check if this is a simple operation with a single value directly expressed // in the parent tag if (node->FirstChild() == NULL || node->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT) { CBooleanLogicValuePtr value = CBooleanLogicValuePtr(newValue()); if (value == NULL || !value->Deserialize(node)) { CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize implicit boolean value definition"); return false; } m_values.push_back(value); return true; } const TiXmlNode *operationNode = node->FirstChild(); while (operationNode != NULL) { std::string tag = operationNode->ValueStr(); if (StringUtils::EqualsNoCase(tag, "and") || StringUtils::EqualsNoCase(tag, "or")) { CBooleanLogicOperationPtr operation = CBooleanLogicOperationPtr(newOperation()); if (operation == NULL) return false; operation->SetOperation(StringUtils::EqualsNoCase(tag, "and") ? BooleanLogicOperationAnd : BooleanLogicOperationOr); if (!operation->Deserialize(operationNode)) { CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize <%s> definition", tag.c_str()); return false; } m_operations.push_back(operation); } else { CBooleanLogicValuePtr value = CBooleanLogicValuePtr(newValue()); if (value == NULL) return false; if (StringUtils::EqualsNoCase(tag, value->GetTag())) { if (!value->Deserialize(operationNode)) { CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize <%s> definition", tag.c_str()); return false; } m_values.push_back(value); } else if (operationNode->Type() == TiXmlNode::TINYXML_ELEMENT) CLog::Log(LOGDEBUG, "CBooleanLogicOperation: unknown <%s> definition encountered", tag.c_str()); } operationNode = operationNode->NextSibling(); } return true; }
// **************************************************************************** // Constructor: ELPipelineBuilder::ELPipelineBuilder // // Programmer: Jeremy Meredith // Creation: August 2, 2012 // // Modifications: // **************************************************************************** ELPipelineBuilder::ELPipelineBuilder(QWidget *parent) : QWidget(parent) { currentPipeline = -1; // Top layout QGridLayout *topLayout = new QGridLayout(this); pipelineChooser = new QComboBox(this); connect(pipelineChooser, SIGNAL(activated(int)), this, SLOT(activatePipeline(int))); topLayout->addWidget(new QLabel("Pipeline: ", this), 0,0, 1,1); topLayout->addWidget(pipelineChooser, 0,1, 1,1); QPushButton *newPipelineBtn = new QPushButton("New Pipeline", this); topLayout->addWidget(newPipelineBtn, 1,0, 1,2); connect(newPipelineBtn, SIGNAL(clicked()), this, SLOT(NewPipeline())); QSplitter *topSplitter = new QSplitter(Qt::Vertical, this); topLayout->addWidget(topSplitter, 3, 0, 1, 2); QGroupBox *pipelineGroup = new QGroupBox("Pipeline", topSplitter); QGridLayout *pipelineLayout = new QGridLayout(pipelineGroup); // // The pipeline tree // tree = new QTreeWidget(pipelineGroup); tree->setHeaderLabels(QStringList() << "Operation" << "Settings"); //tree->setHeaderHidden(true); pipelineLayout->addWidget(tree, 0,0); connect(tree, SIGNAL(itemSelectionChanged()), this, SLOT(rowSelected())); // // The operator menu // QMenu *opMenu = new QMenu(); ///\todo: these choice names must currently match the exact text in /// Operation::GetOperationName. We should loosed this restriction. const char *operations[] = { "Isosurface", "Elevate", "ExternalFace", "Histogram", "SurfaceNormals", "Transform", NULL }; for (int i=0; operations[i] != NULL; i++) { QAction *op= opMenu->addAction(operations[i]); op->setData(QString(operations[i])); connect(op, SIGNAL(triggered()), this, SLOT(newOperation())); } QPushButton *addOpButton = new QPushButton("Add Operation", pipelineGroup); addOpButton->setMenu(opMenu); pipelineLayout->addWidget(addOpButton, 1,0); // // add execute button (probably not the best place for it) // QPushButton *deleteOpButton = new QPushButton("Delete Operation", pipelineGroup); pipelineLayout->addWidget(deleteOpButton, 2, 0); connect(deleteOpButton, SIGNAL(clicked()), this, SLOT(deleteCurrentOp())); // // add execute button (probably not the best place for it) // QPushButton *executeButton = new QPushButton("Execute", pipelineGroup); pipelineLayout->addWidget(executeButton, 3, 0); connect(executeButton, SIGNAL(clicked()), this, SLOT(executePipeline())); // // Settings // settingsGroup = new QGroupBox("Settings", topSplitter); QGridLayout *settingsLayout = new QGridLayout(settingsGroup); // // sources widgets // sourceSettings = new ELSources(settingsGroup); connect(sourceSettings, SIGNAL(sourceChanged()), this, SLOT(sourceUpdated())); settingsLayout->addWidget(sourceSettings); topSplitter->setStretchFactor(0,30); topSplitter->setStretchFactor(1,50); // add one pipeline Pipeline::allPipelines.push_back(new Pipeline); activatePipeline(0); pipelineChooser->addItem(""); }
void LogData::fileChangedOnDisk( const QString& filename ) { LOG(logINFO) << "signalFileChanged " << filename.toStdString(); QFileInfo info( indexingFileName_ ); const auto currentFileId = getFileId( indexingFileName_ ); const auto file_size = indexing_data_.getSize(); LOG(logDEBUG) << "current indexed fileSize=" << file_size; LOG(logDEBUG) << "info file_->size()=" << info.size(); LOG(logDEBUG) << "attached_file_->size()=" << attached_file_->size(); LOG(logDEBUG) << "attached_file_id_ index " << attached_file_id_.fileIndex; LOG(logDEBUG) << "currentFileId index " << currentFileId.fileIndex; // In absence of any clearer information, we use the following size comparison // to determine whether we are following the same file or not (i.e. the file // has been moved and the inode we are following is now under a new name, if for // instance log has been rotated). We want to follow the name so we have to reopen // the file to ensure we are reading the right one. // This is a crude heuristic but necessary for notification services that do not // give details (e.g. kqueues) const bool isFileIdChanged = attached_file_id_ != currentFileId; if ( isFileIdChanged || ( info.size() != attached_file_->size() ) || ( attached_file_->openMode() == QIODevice::NotOpen ) ) { LOG(logINFO) << "Inconsistent size, or file index, the file might have changed, re-opening"; reOpenFile(); // We don't force a (slow) full reindex as this routinely happens if // the file is appended quickly. // This means we can occasionally have false negatives (should be dealt with at // a lower level): e.g. if a new file is created with the same name as the old one // and with a size greater than the old one (should be rare in practice). } std::function<std::shared_ptr<LogDataOperation>()> newOperation; const auto real_file_size = attached_file_->size(); if ( isFileIdChanged || real_file_size < file_size ) { fileChangedOnDisk_ = Truncated; LOG(logINFO) << "File truncated"; newOperation = std::make_shared<FullIndexOperation>; } else if ( real_file_size == file_size ) { LOG(logINFO) << "No change in file"; if ( keepFileClosed_ ) { QMutexLocker locker( &fileMutex_ ); attached_file_->close(); } } else if ( fileChangedOnDisk_ != DataAdded ) { fileChangedOnDisk_ = DataAdded; LOG(logINFO) << "New data on disk"; newOperation = std::make_shared<PartialIndexOperation>; } if ( newOperation ) { enqueueOperation( newOperation() ); lastModifiedDate_ = info.lastModified(); emit fileChanged( fileChangedOnDisk_ ); } }