Beispiel #1
0
void Lyrics::layout1()
      {
      setPos(textStyle().offset(spatium()));
      Text::layout1();
      if (!parent()) // palette & clone trick
          return;

      ChordRest* cr = chordRest();
      const QList<Lyrics*>* ll = &(cr->lyricsList());

      qreal lh = lineSpacing() * score()->styleD(StyleIdx::lyricsLineHeight);
      int line = ll->indexOf(this);
      qreal y  = lh * line + point(score()->styleS(StyleIdx::lyricsDistance));
      qreal x  = 0.0;

      //
      // parse leading verse number and/or punctuation, so we can factor it into layout separately
      // TODO: provide a way to disable this
      //
      bool hasNumber = false; // _verseNumber;
      qreal adjust = 0.0;
      QString s = plainText(true);
      // find:
      // 1) string of numbers and non-word characters at start of syllable
      // 2) at least one other character (indicating start of actual lyric)
      QRegularExpression leadingPattern("(^[\\d\\W]+)([^\\d\\W]+)");
      QRegularExpressionMatch leadingMatch = leadingPattern.match(s);
      if (leadingMatch.hasMatch()) {
            // leading string
            QString s1 = leadingMatch.captured(1);
            // actual lyric
            //QString s2 = leadingMatch.captured(2);
            Text leading(*this);
            leading.setPlainText(s1);
            leading.layout1();
            adjust = leading.width();
            if (!s1.isEmpty() && s1[0].isDigit())
                  hasNumber = true;
            }

      if (textStyle().align() & AlignmentFlags::HCENTER) {
            //
            // center under notehead, not origin
            // however, lyrics that are melismas or have verse numbers will be forced to left alignment
            // TODO: provide a way to disable the automatic left alignment
            //
            qreal maxWidth;
            if (cr->type() == Element::Type::CHORD)
                  maxWidth = static_cast<Chord*>(cr)->maxHeadWidth();
            else
                  maxWidth = cr->width();       // TODO: exclude ledger line for multivoice rest?
            qreal nominalWidth = symWidth(SymId::noteheadBlack);
            if (!isMelisma() && !hasNumber)     // center under notehead
                  x +=  nominalWidth * .5 - cr->x() - adjust * 0.5;
            else                                // force left alignment
                  x += (width() + nominalWidth - maxWidth) * .5 - cr->x() - adjust;
            }
      else {
            // even for left aligned syllables, ignore leading verse numbers and/or punctuation
            x -= adjust;
            }

      rxpos() += x;
      rypos() += y;

      if (_ticks > 0 || _syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
            if (_separator == nullptr) {
                  _separator = new LyricsLine(score());
                  _separator->setTick(cr->tick());
                  score()->addUnmanagedSpanner(_separator);
                  }
            _separator->setParent(this);
            _separator->setTick(cr->tick());
            _separator->setTrack(track());
            _separator->setTrack2(track());
#if defined(USE_FONT_DASH_METRIC)
            // if font parameters different from font cached values, compute new dash values from font metrics
            if (textStyle().family() != g_fontFamily && textStyle().size() != g_fontSize) {
                  QFontMetricsF     fm    = textStyle().fontMetrics(spatium());
                  QRectF            r     = fm.tightBoundingRect("\u2013");   // U+2013 EN DASH
                  g_cachedDashY           = _dashY          = r.y() + (r.height() * HALF);
                  g_cachedDashLength      = _dashLength     = r.width();
   #if defined(USE_FONT_DASH_TICKNESS)
                  g_cachedDashThickness   = _dashThickness  = r.height();
   #endif
                  g_fontFamily            = textStyle().family();
                  g_fontSize              = textStyle().size();
                  }
            // if same font, use cached values
            else {
                  _dashY                  = g_cachedDashY;
                  _dashLength             = g_cachedDashLength;
   #if defined(USE_FONT_DASH_TICKNESS)
                  _dashThickness          = g_cachedDashThickness;
   #endif
                  }
#endif
            }
      else
            if (_separator != nullptr) {
                  _separator->unchain();
                  delete _separator;
                  _separator = nullptr;
                  }
      }
Beispiel #2
0
bool CliPlugin::readListLine(const QString& line)
{
    static const QLatin1String archiveInfoDelimiter1("--"); // 7z 9.13+
    static const QLatin1String archiveInfoDelimiter2("----"); // 7z 9.04
    static const QLatin1String entryInfoDelimiter("----------");
    const QRegularExpression rxComment(QStringLiteral("Comment = .+$"));

    if (m_parseState == ParseStateTitle) {

        const QRegularExpression rxVersionLine(QStringLiteral("^p7zip Version ([\\d\\.]+) .*$"));
        QRegularExpressionMatch matchVersion = rxVersionLine.match(line);
        if (matchVersion.hasMatch()) {
            m_parseState = ParseStateHeader;
            const QString p7zipVersion = matchVersion.captured(1);
            qCDebug(ARK) << "p7zip version" << p7zipVersion << "detected";
        }

    } else if (m_parseState == ParseStateHeader) {

        if (line.startsWith(QStringLiteral("Listing archive:"))) {
            qCDebug(ARK) << "Archive name: "
                     << line.right(line.size() - 16).trimmed();
        } else if ((line == archiveInfoDelimiter1) ||
                   (line == archiveInfoDelimiter2)) {
            m_parseState = ParseStateArchiveInformation;
        } else if (line.contains(QStringLiteral("Error: "))) {
            qCWarning(ARK) << line.mid(7);
        }

    } else if (m_parseState == ParseStateArchiveInformation) {

        if (line == entryInfoDelimiter) {
            m_parseState = ParseStateEntryInformation;
        } else if (line.startsWith(QStringLiteral("Type = "))) {
            const QString type = line.mid(7).trimmed();
            qCDebug(ARK) << "Archive type: " << type;

            if (type == QLatin1String("7z")) {
                m_archiveType = ArchiveType7z;
            } else if (type == QLatin1String("bzip2")) {
                m_archiveType = ArchiveTypeBZip2;
            } else if (type == QLatin1String("gzip")) {
                m_archiveType = ArchiveTypeGZip;
            } else if (type == QLatin1String("xz")) {
                m_archiveType = ArchiveTypeXz;
            } else if (type == QLatin1String("tar")) {
                m_archiveType = ArchiveTypeTar;
            } else if (type == QLatin1String("zip")) {
                m_archiveType = ArchiveTypeZip;
            } else if (type == QLatin1String("Rar")) {
                m_archiveType = ArchiveTypeRar;
            } else {
                // Should not happen
                qCWarning(ARK) << "Unsupported archive type";
                return false;
            }

        } else if (rxComment.match(line).hasMatch()) {
            m_parseState = ParseStateComment;
            m_comment.append(line.section(QLatin1Char('='), 1) + QLatin1Char('\n'));
        }

    } else if (m_parseState == ParseStateComment) {

        if (line == entryInfoDelimiter) {
            m_parseState = ParseStateEntryInformation;
            if (!m_comment.trimmed().isEmpty()) {
                m_comment = m_comment.trimmed();
                m_linesComment = m_comment.count(QLatin1Char('\n')) + 1;
                qCDebug(ARK) << "Found a comment with" << m_linesComment << "lines";
            }
        } else {
            m_comment.append(line + QLatin1Char('\n'));
        }

    } else if (m_parseState == ParseStateEntryInformation) {

        if (line.startsWith(QStringLiteral("Path = "))) {
            const QString entryFilename =
                QDir::fromNativeSeparators(line.mid(7).trimmed());
            m_currentArchiveEntry.clear();
            m_currentArchiveEntry[FileName] = entryFilename;
            m_currentArchiveEntry[InternalID] = entryFilename;
        } else if (line.startsWith(QStringLiteral("Size = "))) {
            m_currentArchiveEntry[ Size ] = line.mid(7).trimmed();
        } else if (line.startsWith(QStringLiteral("Packed Size = "))) {
            // #236696: 7z files only show a single Packed Size value
            //          corresponding to the whole archive.
            if (m_archiveType != ArchiveType7z) {
                m_currentArchiveEntry[CompressedSize] = line.mid(14).trimmed();
            }
        } else if (line.startsWith(QStringLiteral("Modified = "))) {
            m_currentArchiveEntry[ Timestamp ] =
                QDateTime::fromString(line.mid(11).trimmed(),
                                      QStringLiteral("yyyy-MM-dd hh:mm:ss"));
        } else if (line.startsWith(QStringLiteral("Attributes = "))) {
            const QString attributes = line.mid(13).trimmed();

            const bool isDirectory = attributes.startsWith(QLatin1Char('D'));
            m_currentArchiveEntry[ IsDirectory ] = isDirectory;
            if (isDirectory) {
                const QString directoryName =
                    m_currentArchiveEntry[FileName].toString();
                if (!directoryName.endsWith(QLatin1Char('/'))) {
                    const bool isPasswordProtected = (line.at(12) == QLatin1Char('+'));
                    m_currentArchiveEntry[FileName] =
                        m_currentArchiveEntry[InternalID] = QString(directoryName + QLatin1Char('/'));
                    m_currentArchiveEntry[ IsPasswordProtected ] =
                        isPasswordProtected;
                }
            }

            m_currentArchiveEntry[ Permissions ] = attributes.mid(1);
        } else if (line.startsWith(QStringLiteral("CRC = "))) {
            m_currentArchiveEntry[ CRC ] = line.mid(6).trimmed();
        } else if (line.startsWith(QStringLiteral("Method = "))) {
            m_currentArchiveEntry[ Method ] = line.mid(9).trimmed();
        } else if (line.startsWith(QStringLiteral("Encrypted = ")) &&
                   line.size() >= 13) {
            m_currentArchiveEntry[ IsPasswordProtected ] = (line.at(12) == QLatin1Char('+'));
        } else if (line.startsWith(QStringLiteral("Block = ")) ||
                   line.startsWith(QStringLiteral("Version = "))) {
            if (m_currentArchiveEntry.contains(FileName)) {
                emit entry(m_currentArchiveEntry);
            }
        }
    }

    return true;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
  qInstallMessageHandler(sharedLogOutput);

  qInfo() << "QRenderDoc initialising.";

  QString filename = "";
  bool temp = false;

  for(int i = 0; i < argc; i++)
  {
    if(!QString::compare(argv[i], "--tempfile", Qt::CaseInsensitive))
      temp = true;
  }

  QString remoteHost = "";
  uint remoteIdent = 0;

  for(int i = 0; i + 1 < argc; i++)
  {
    if(!QString::compare(argv[i], "--REMOTEACCESS", Qt::CaseInsensitive))
    {
      QRegularExpression regexp("^([a-zA-Z0-9_-]+:)?([0-9]+)$");

      QRegularExpressionMatch match = regexp.match(argv[i + 1]);

      if(match.hasMatch())
      {
        QString host = match.captured(1);

        if(host.length() > 0 && host[host.length() - 1] == ':')
          host.chop(1);

        bool ok = false;
        uint32_t ident = match.captured(2).toUInt(&ok);

        if(ok)
        {
          remoteHost = host;
          remoteIdent = ident;
        }
      }
    }
  }

  if(argc > 1)
  {
    filename = argv[argc - 1];
    QFileInfo checkFile(filename);
    if(!checkFile.exists() || !checkFile.isFile())
      filename = "";
  }

  argc += 2;

  char **argv_mod = new char *[argc];

  for(int i = 0; i < argc - 2; i++)
    argv_mod[i] = argv[i];

  char arg[] = "-platformpluginpath";
  QString path = QFileInfo(argv[0]).absolutePath();
  QByteArray pathChars = path.toUtf8();

  argv_mod[argc - 2] = arg;
  argv_mod[argc - 1] = pathChars.data();

  QApplication application(argc, argv_mod);

  {
    PersistantConfig config;

    {
      QString configPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
      QDir dir(configPath);

      if(!dir.exists())
        dir.mkpath(configPath);
    }

    QString configFilename = CaptureContext::ConfigFile("UI.config");

    if(!config.Deserialize(configFilename))
    {
      RDDialog::critical(
          NULL, "Error loading config",
          QString(
              "Error loading config file\n%1\nA default config is loaded and will be saved out.")
              .arg(configFilename));
    }

    config.SetupFormatting();

    GUIInvoke::init();

    CaptureContext ctx(filename, remoteHost, remoteIdent, temp, config);

    while(ctx.isRunning())
    {
      application.processEvents(QEventLoop::WaitForMoreEvents);
      QCoreApplication::sendPostedEvents();
    }

    config.Serialize();
  }

  delete[] argv_mod;

  return 0;
}
Beispiel #4
0
bool ZInstrument::loadSfz(const QString& s)
      {
      _program = 0;
      QFileInfo fi(s);
      QString path = fi.absolutePath();

      QStringList fileContents = readFile(s);

      if (fileContents.empty()) {
            return false;
            }

      SfzControl c;
      c.init();
      c.defines.clear();
      for (int i = 0;i < 128; i++)
            c.set_cc[i] = -1;

      int idx = 0;
      bool inBlockComment = false;
      // preprocessor
      while(idx < fileContents.size()) {
            QRegularExpression findWithSpaces("\"(.+)\"");
            QRegularExpression comment("//.*$");
            QRegularExpression trailingSpacesOrTab("^[\\s\\t]*");
            QRegularExpressionMatch foundWithSpaces;
            QString curLine = fileContents[idx];
            QString curLineCopy = curLine;
            bool nextIsImportant = false;
            int idxBlockComment = 0;
            int from = 0;

            for (QChar chr : curLineCopy) {
                  bool terminated = false;

                  if (nextIsImportant) {
                        nextIsImportant = false;
                        if (inBlockComment && chr == '/') { // found block end
                              inBlockComment = false;
                              terminated = true;
                              curLine.remove(from, idxBlockComment - from + 1);
                              idxBlockComment = from - 1;
                              }
                        else if (!inBlockComment && chr == '*') { // found block start
                              inBlockComment = true;
                              terminated = true;
                              from = idxBlockComment - 1;
                              }
                        }

                  if (!terminated && inBlockComment && chr == '*')
                        nextIsImportant = true;
                  else if (!terminated && !inBlockComment && chr == '/')
                        nextIsImportant = true;

                  idxBlockComment++;
                  }

            if (inBlockComment)
                  curLine.remove(from, curLine.size() - from);

            curLine = curLine.remove(comment);
            curLine.remove(trailingSpacesOrTab);
            fileContents[idx] = curLine;

            if (curLine.startsWith("#define")) {
                  QStringList define = curLine.split(" ");
                  foundWithSpaces = findWithSpaces.match(curLine);
                  if (define.size() == 3)
                        c.defines.insert(std::pair<QString, QString>(define[1], define[2]));
                  else if(foundWithSpaces.hasMatch())
                        c.defines.insert(std::pair<QString, QString>(define[1], foundWithSpaces.captured(1)));
                  fileContents.removeAt(idx);
                  }
            else if (curLine.startsWith("#include")) {
                  foundWithSpaces = findWithSpaces.match(curLine);
                  if (foundWithSpaces.hasMatch()) {
                        QString newFilename = foundWithSpaces.captured(1);

                        for(auto define : c.defines) {
                              newFilename.replace(define.first, define.second);
                              }

                        QStringList newFileContents = readFile(path + "/" + newFilename);
                        if (newFileContents.empty())
                              return false;

                        int offset = 1;
                        for (QString newFileLine : newFileContents) {
                              fileContents.insert(idx+offset, newFileLine);
                              offset++;
                              }

                        fileContents.removeAt(idx);
                        }
                  }
            else if (curLine.isEmpty())
                  fileContents.removeAt(idx);
            else
                  idx++;
            }

      int total = fileContents.size();
      SfzRegion r;
      SfzRegion g;      // group
      SfzRegion glob;
      r.init(path);
      g.init(path);
      glob.init(path);

      bool groupMode = false;
      bool globMode = false;
      zerberus->setLoadProgress(0);

      for (int idx = 0; idx < fileContents.size(); idx++) {
            QString curLine = fileContents[idx];
            zerberus->setLoadProgress(((qreal) idx * 100) /  (qreal) total);

            if (zerberus->loadWasCanceled())
                  return false;
            if (curLine.startsWith("<global>")) {
                  if (!globMode && !groupMode && !r.isEmpty())
                        addRegion(r);
                  glob.init(path);
                  g.init(path); // global also resets group
                  r.init(path);
                  globMode = true;
                  }
            if (curLine.startsWith("<group>")) {
                  if (!groupMode && !globMode && !r.isEmpty())
                        addRegion(r);
                  g.init(path);
                  if (globMode) {
                        glob = r;
                        globMode = false;
                        }
                  else {
                        r = glob; // initialize group with global values
                        }
                  groupMode = true;
                  curLine = curLine.mid(7);
                  }
            else if (curLine.startsWith("<region>")) {
                  if (groupMode) {
                        g = r;
                        groupMode = false;
                        }
                  else if (globMode) {
                        glob = r;
                        g = glob;
                        globMode = false;
                        }
                  else {
                        if (!r.isEmpty())
                              addRegion(r);
                        r = g;  // initialize next region with group values
                        }
                  curLine = curLine.mid(8);
                  }
            else if (curLine.startsWith("<control>"))
                  c.init();

            QRegularExpression re("\\s?([\\w\\$]+)="); // defines often use the $-sign
            QRegularExpressionMatchIterator i = re.globalMatch(curLine);

            while (i.hasNext()) {
                  QRegularExpressionMatch match = i.next();
                  int si = match.capturedEnd();
                  int ei;
                  if (i.hasNext()) {
                        QRegularExpressionMatch nextMatch = i.peekNext();
                        ei = nextMatch.capturedStart();
                        }
                  else
                        ei = curLine.size();
                  QString s = curLine.mid(si, ei-si);
                  r.readOp(match.captured(1), s, c);
                  }
            }

      for (int i = 0; i < 128; i++)
            _setcc[i] = c.set_cc[i];

      zerberus->setLoadProgress(100);
      if (!groupMode && !globMode && !r.isEmpty())
            addRegion(r);
      return true;
      }
void SyncController::run(bool saveLog, QFile* log)
{
    this->saveLog = saveLog;
    this->log = log;

    input.open(stdin, QIODevice::ReadOnly);
    output.open(stdout, QIODevice::WriteOnly);

    quint32 cnt;

    QByteArray ba = input.read(4);
    QDataStream modify(&ba, QIODevice::ReadOnly);
    modify>>cnt;
    if(saveLog)
    {
        log->write("\nBytes for read: "+QByteArray::number(cnt));
        log->flush();
    }

    ba.clear();
    forever
    {
        if(saveLog)
        {
            log->write("\nTry to read : "+QByteArray::number(cnt-ba.length())+" bytes");
            log->flush();
        }

        ba.append(input.read(cnt-ba.length()));

        if ((quint32)ba.length() >= cnt)
        {
            if(saveLog)
            {
                log->write("\nEnd readind - bytes limit reached");
                log->flush();
            }
            break;
        }

        if(saveLog)
        {
            log->write("\nBytes readed (part of packet): "+QByteArray::number(ba.length())+" needed: "+QByteArray::number(cnt));
            log->flush();
        }

        if (!input.waitForReadyRead(30000))
        {
            if(saveLog)
            {
                log->write("\nEnd readind - wait limit reached");
                if(!input.atEnd())
                    log->write(" and not at end");
                log->flush();
            }
            if(input.atEnd())
                break;
        }
        //cnt -= ba.length();
        /*
        if(saveLog)
        {
            log->write("\nLets dec waited to : "+QByteArray::number(cnt));
            log->flush();
        }
        */

    }

    if(saveLog)
    {
        log->write("\nBytes readed: "+QByteArray::number(ba.length()));
        log->flush();
    }


    QByteArray message;
    QDataStream in(&ba, QIODevice::ReadOnly);
    in.setVersion(QDataStream::Qt_5_4);

    in >> message;

    message = qUncompress(message);

    QByteArray command = message.left(message.indexOf('\n'));
    message = message.mid(command.length()+1);

    if(saveLog)
    {
        log->write("\nCommand:\n"+command);
        log->write("\nInput:\n"+message);
        log->flush();
    }

    QByteArray answer;
    if (command.startsWith("Execute xml"))
    {
        sc.setXmlFile(message);

        QRegularExpression reg("send istate every (?<interations>\\d+) iterations");
        QRegularExpressionMatch match = reg.match(command);

        if(match.hasMatch())
        {
            iterationsToSend = match.captured("interations").toInt();
            iterationsCount = 1;
            connect(&sc, SIGNAL(iterationFinished(SyncState)), this, SLOT(iterationFinished(SyncState)));
        }

        sc.run();

        if(sc.getState()==SyncCore::syncFail)
        {
            answer = "Error\n"+sc.errorString().toUtf8();
        }
        else
        {
            QRegularExpression reg("return connection \"(?<connection>.+)\"");
            QRegularExpressionMatch match = reg.match(command);
            if(match.hasMatch())
            {
                answer = "Result xml\n"+sc.dump(match.captured("connection"));
            }
            else
            {
                QRegularExpression reg("return states");
                QRegularExpressionMatch match = reg.match(command);
                if(match.hasMatch())
                {
                    QMap<int, SyncState> syncs = sc.getSyncsCompleted();
                    if(syncs.contains(2))
                    {
                        SyncState ss = syncs.value(2);

                        answer = "Result states "+ss.name.toUtf8()
                                +" checked:"+QByteArray::number(ss.num)
                                +" inserts:"+QByteArray::number(ss.numIns)
                                +" insfail:"+QByteArray::number(ss.numInsFail)
                                +" deletes:"+QByteArray::number(ss.numDel)
                                +" delfail:"+QByteArray::number(ss.numDelFail)
                                +" updates:"+QByteArray::number(ss.numUpd)
                                +" updfail:"+QByteArray::number(ss.numUpdFail);
                    }
                }
            }
        }
    }

    if(saveLog)
    {
        log->write("\nOutput:\n"+answer);
        log->write("\nMessage:\n"+formatMessage(answer).toHex());
    }

    output.write(formatMessage(answer));
    output.flush();
    output.close();

    input.close();
}
bool SeimiServerHandler::handleRequest(Pillow::HttpConnection *connection){
    QString method = connection->requestMethod();
    QString path = connection->requestPath();
    if(method == "GET"){
        connection->writeResponse(405, Pillow::HttpHeaderCollection(),"Method 'GET' is not supprot,please use 'POST'");
        return true;
    }
    if(path != "/doload"){
        return false;
    }
//    QString url = QUrl::fromPercentEncoding(connection->requestParamValue(urlP).toUtf8());
    QString url = connection->requestParamValue(urlP);
    int renderTime = connection->requestParamValue(renderTimeP).toInt();
    QString proxyStr = connection->requestParamValue(proxyP);
    QString contentType = connection->requestParamValue(contentTypeP);
    QString outImgSizeStr = connection->requestParamValue(outImgSizeP);
    QString ua = connection->requestParamValue(uaP);
//    QString jscript = QUrl::fromPercentEncoding(connection->requestParamValue(scriptP).toUtf8());
    QString jscript = connection->requestParamValue(scriptP);
    QString postParamJson = connection->requestParamValue(postParamP);
    int resourceTimeout = connection->requestParamValue(resourceTimeoutP).toInt();
    Pillow::HttpHeaderCollection headers;
    headers << Pillow::HttpHeader("Pragma", "no-cache");
    headers << Pillow::HttpHeader("Expires", "-1");
    headers << Pillow::HttpHeader("Cache-Control", "no-cache");
    try{
        QEventLoop eventLoop;
        SeimiPage *seimiPage=new SeimiPage(this);
        if(!proxyStr.isEmpty()){
            QRegularExpression reProxy("(?<protocol>http|https|socket)://(?:(?<user>\\w*):(?<password>\\w*)@)?(?<host>[\\w.]+)(:(?<port>\\d+))?");
            QRegularExpressionMatch matchProxy = reProxy.match(proxyStr);
            if(matchProxy.hasMatch()){
                QNetworkProxy proxy;
                if(matchProxy.captured("protocol") == "socket"){
                    proxy.setType(QNetworkProxy::Socks5Proxy);
                }else{
                    proxy.setType(QNetworkProxy::HttpProxy);
                }
                proxy.setHostName(matchProxy.captured("host"));
                proxy.setPort(matchProxy.captured("port").toInt()==0?80:matchProxy.captured("port").toInt());
                proxy.setUser(matchProxy.captured("user"));
                proxy.setPassword(matchProxy.captured("password"));

                seimiPage->setProxy(proxy);
            }else {
                qWarning("[seimi] proxy pattern error, proxy = %s",proxyStr.toUtf8().constData());
            }
        }
        seimiPage->setScript(jscript);
        seimiPage->setPostParam(postParamJson);
        qInfo("[seimi] TargetUrl:%s ,RenderTime(ms):%d",url.toUtf8().constData(),renderTime);
        int useCookieFlag = connection->requestParamValue(useCookieP).toInt();
        seimiPage->setUseCookie(useCookieFlag==1);
        QObject::connect(seimiPage,SIGNAL(loadOver()),&eventLoop,SLOT(quit()));
        seimiPage->toLoad(url,renderTime,ua,resourceTimeout);
        eventLoop.exec();

        if(contentType == "pdf"){
            headers << Pillow::HttpHeader("Content-Type", "application/pdf");
            QByteArray pdfContent = seimiPage->generatePdf();
            QCryptographicHash md5sum(QCryptographicHash::Md5);
            md5sum.addData(pdfContent);
            QByteArray etag = md5sum.result().toHex();
            headers << Pillow::HttpHeader("ETag", etag);
            connection->writeResponse(200,headers,pdfContent);
        }else if(contentType == "img"){
            headers << Pillow::HttpHeader("Content-Type", "image/png");
            QSize targetSize;
            if(!outImgSizeStr.isEmpty()){
                QRegularExpression reImgSize("(?<xSize>\\d+)(?:x|X)(?<ySize>\\d+)");
                QRegularExpressionMatch matchImgSize = reImgSize.match(outImgSizeStr);
                if(matchImgSize.hasMatch()){
                    targetSize.setWidth(matchImgSize.captured("xSize").toInt());
                    targetSize.setHeight(matchImgSize.captured("ySize").toInt());
                }
            }
            QByteArray imgContent = seimiPage->generateImg(targetSize);
            QCryptographicHash md5sum(QCryptographicHash::Md5);
            md5sum.addData(imgContent);
            QByteArray etag = md5sum.result().toHex();
            headers << Pillow::HttpHeader("ETag", etag);
            connection->writeResponse(200,headers,imgContent);
        }else{
            headers << Pillow::HttpHeader("Content-Type", "text/html;charset=utf-8");
            QString defBody = "<html>null</html>";
            connection->writeResponse(200, headers,seimiPage->getContent().isEmpty()?defBody.toUtf8():seimiPage->getContent().toUtf8());
        }
        seimiPage->deleteLater();
    }catch (std::exception& e) {
        headers << Pillow::HttpHeader("Content-Type", "text/html;charset=utf-8");
        QString errMsg = "<html>server error,please try again.</html>";
        qInfo("[seimi error] Page error, url: %s, errorMsg: %s", url.toUtf8().constData(), QString(QLatin1String(e.what())).toUtf8().constData());
        connection->writeResponse(500, headers, errMsg.toUtf8());
    }catch (...) {
        qInfo() << "server error!";
        headers << Pillow::HttpHeader("Content-Type", "text/html;charset=utf-8");
        QString errMsg = "<html>server error,please try again.</html>";
        connection->writeResponse(500, headers, errMsg.toUtf8());

    }
    return true;
}
Beispiel #7
0
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QCoreApplication::setApplicationName("evnav-cli");
    QCoreApplication::setApplicationVersion("0.1");

    QCommandLineParser parser;
    parser.setApplicationDescription("electric vehicule trip planner");
    parser.addHelpOption();
    parser.addVersionOption();
    parser.addPositionalArgument("osrm", "path to osrm file");
    parser.addPositionalArgument("charger", "path to json charger file");

    parser.process(app);
    const QStringList args = parser.positionalArguments();

    if (args.size() < 2) {
        qDebug() << "missing arguments";
        parser.showHelp(1);
    }

    qDebug() << "loading street data...";
    Evnav evnav(args.at(0));

    qDebug() << "loading chargers...";
    ChargerProvider provider;
    provider.loadJson(args.at(1));
    ChargerProvider dcfc = provider.filter(ChargerProvider::fastChargerFilter);
    qDebug() << "fast chargers found:" << dcfc.size();

    evnav.setChargerProvider(&dcfc);
    evnav.initGraph();

    EvnavServer handler(&evnav);
    EvnavServer *handlerPtr = &handler;

    QRegularExpression evnavUrl{"^/route/v1/evnav/.*"};
    evnavUrl.optimize();

    QHttpServer srv;
    srv.listen(QHostAddress::Any, 8080, [&](QHttpRequest *req, QHttpResponse *res) {
        QRegularExpressionMatch match = evnavUrl.match(req->url().path());
        if (match.hasMatch()) {
            req->onEnd([res, req, handlerPtr]() {
                handlerPtr->handleRequest(req, res);
            });
        } else {
            res->setStatusCode(qhttp::ESTATUS_NOT_FOUND);
            res->end();
        }
        return;

    });

    if (!srv.isListening()) {
        fprintf(stderr, "error spawning the server\n");
        return -1;
    }

    fprintf(stdout, "server listening\n");
    return app.exec();
}
Beispiel #8
0
void FlatTextarea::parseLinks() { // some code is duplicated in text.cpp!
	LinkRanges newLinks;

	QString text(toPlainText());
	if (text.isEmpty()) {
		if (!_links.isEmpty()) {
			_links.clear();
			emit linksChanged();
		}
		return;
	}

	initLinkSets();

	int32 len = text.size();
	const QChar *start = text.unicode(), *end = start + text.size();
	for (int32 offset = 0, matchOffset = offset; offset < len;) {
		QRegularExpressionMatch m = reDomain().match(text, matchOffset);
		if (!m.hasMatch()) break;

		int32 domainOffset = m.capturedStart();

		QString protocol = m.captured(1).toLower();
		QString topDomain = m.captured(3).toLower();

		bool isProtocolValid = protocol.isEmpty() || validProtocols().contains(hashCrc32(protocol.constData(), protocol.size() * sizeof(QChar)));
		bool isTopDomainValid = !protocol.isEmpty() || validTopDomains().contains(hashCrc32(topDomain.constData(), topDomain.size() * sizeof(QChar)));

		if (protocol.isEmpty() && domainOffset > offset + 1 && *(start + domainOffset - 1) == QChar('@')) {
			QString forMailName = text.mid(offset, domainOffset - offset - 1);
			QRegularExpressionMatch mMailName = reMailName().match(forMailName);
			if (mMailName.hasMatch()) {
				offset = matchOffset = m.capturedEnd();
				continue;
			}
		}
		if (!isProtocolValid || !isTopDomainValid) {
			offset = matchOffset = m.capturedEnd();
			continue;
		}

		QStack<const QChar*> parenth;
		const QChar *domainEnd = start + m.capturedEnd(), *p = domainEnd;
		for (; p < end; ++p) {
			QChar ch(*p);
			if (chIsLinkEnd(ch)) break; // link finished
			if (chIsAlmostLinkEnd(ch)) {
				const QChar *endTest = p + 1;
				while (endTest < end && chIsAlmostLinkEnd(*endTest)) {
					++endTest;
				}
				if (endTest >= end || chIsLinkEnd(*endTest)) {
					break; // link finished at p
				}
				p = endTest;
				ch = *p;
			}
			if (ch == '(' || ch == '[' || ch == '{' || ch == '<') {
				parenth.push(p);
			} else if (ch == ')' || ch == ']' || ch == '}' || ch == '>') {
				if (parenth.isEmpty()) break;
				const QChar *q = parenth.pop(), open(*q);
				if ((ch == ')' && open != '(') || (ch == ']' && open != '[') || (ch == '}' && open != '{') || (ch == '>' && open != '<')) {
					p = q;
					break;
				}
			}
		}
		if (p > domainEnd) { // check, that domain ended
			if (domainEnd->unicode() != '/' && domainEnd->unicode() != '?') {
				matchOffset = domainEnd - start;
				continue;
			}
		}
		newLinks.push_back(qMakePair(domainOffset - 1, p - start - domainOffset + 2));
		offset = matchOffset = p - start;
	}

	if (newLinks != _links) {
		_links = newLinks;
		emit linksChanged();
	}
}
void VersionResolveWorker::resolve()
{
    emit started();
#ifdef QT_DEBUG
    qDebug() << "Using 'java' from" << ProcessUtils::javaExe();
#endif
    bool found = false;
    const QString java = ProcessUtils::javaExe();
    if (!java.isEmpty()) {
        ProcessResult result = ProcessUtils::runCommand(java, QStringList() << "-version");
#ifdef QT_DEBUG
        qDebug() << "Java returned code" << result.code;
#endif
        if (result.code == 0) {
#ifdef QT_DEBUG
            qDebug() << "Java returned" << result.output[0];
#endif
            QRegularExpression regexp(REGEXP_JAVA_VERSION);
            QRegularExpressionMatch match = regexp.match(result.output[0]);
            if (match.hasMatch()) {
                emit versionResolved("java", match.captured(1));
                found = true;
            }
        }
    }
    if (!found) {
        emit versionResolved("java", QString());
    }
#ifdef QT_DEBUG
    qDebug() << "Using 'apktool' from" << ProcessUtils::apktoolJar();
#endif
    found = false;
    const QString apktool = ProcessUtils::apktoolJar();
    if (!java.isEmpty() && !apktool.isEmpty()) {
        QStringList args;
        args << "-jar" << apktool;
        args << "--version";
        ProcessResult result = ProcessUtils::runCommand(java, args);
#ifdef QT_DEBUG
        qDebug() << "Apktool returned code" << result.code;
#endif
        if (result.code == 0) {
#ifdef QT_DEBUG
            qDebug() << "Apktool returned" << result.output[0];
#endif
            emit versionResolved("apktool", result.output[0].trimmed());
            found = true;
        }
    }
    if (!found) {
        emit versionResolved("apktool", QString());
    }
#ifdef QT_DEBUG
    qDebug() << "Using 'jadx' from" << ProcessUtils::jadxExe();
#endif
    found = false;
    const QString jadx = ProcessUtils::jadxExe();
    if (!jadx.isEmpty()) {
        ProcessResult result = ProcessUtils::runCommand(jadx, QStringList() << "--version");
#ifdef QT_DEBUG
        qDebug() << "Jadx returned code" << result.code;
#endif
        if (result.code == 0) {
#ifdef QT_DEBUG
            qDebug() << "Jadx returned" << result.output[0];
#endif
            emit versionResolved("jadx", result.output[0].trimmed());
            found = true;
        }
    }
    if (!found) {
        emit versionResolved("jadx", QString());
    }
#ifdef QT_DEBUG
    qDebug() << "Using 'adb' from" << ProcessUtils::adbExe();
#endif
    found = false;
    const QString adb = ProcessUtils::adbExe();
    if (!adb.isEmpty()) {
        ProcessResult result = ProcessUtils::runCommand(adb, QStringList() << "--version");
#ifdef QT_DEBUG
        qDebug() << "ADB returned code" << result.code;
#endif
        if (result.code == 0) {
#ifdef QT_DEBUG
            qDebug() << "ADB returned" << result.output[0];
#endif
            QRegularExpression regexp(REGEXP_ADB_VERSION);
            QRegularExpressionMatch match = regexp.match(result.output[0]);
            if (match.hasMatch()) {
                emit versionResolved("adb", match.captured(1));
                found = true;
            }
        }
    }
    if (!found) {
        emit versionResolved("adb", QString());
    }
#ifdef QT_DEBUG
    qDebug() << "Using 'uas' from" << ProcessUtils::uberApkSignerJar();
#endif
    found = false;
    const QString uas = ProcessUtils::uberApkSignerJar();
    if (!java.isEmpty() && !uas.isEmpty()) {
        QStringList args;
        args << "-jar" << uas;
        args << "--version";
        ProcessResult result = ProcessUtils::runCommand(java, args);
#ifdef QT_DEBUG
        qDebug() << "Uber APK signer returned code" << result.code;
#endif
        if (result.code == 0) {
#ifdef QT_DEBUG
            qDebug() << "Uber APK signer returned" << result.output[0];
#endif
            QRegularExpression regexp(REGEXP_UAS_VERSION);
            QRegularExpressionMatch match = regexp.match(result.output[0]);
            if (match.hasMatch()) {
                emit versionResolved("uas", match.captured(1));
                found = true;
            }
        }
        if (!found) {
            emit versionResolved("uas", QString());
        }
    }
    emit finished();
}
Private::Data Private::GenerateTree(aop::CallGraph && cg)
{
    Private::Data data
    {
        Private::Node(),
        std::move(cg.table),
        nullptr,
        nullptr
    };

    QVector<QString> short_name(cg.root.value + 1U);
    QVector<QString> signature (cg.root.value + 1U);
    {   /* get a map from id to signature */
        short_name[0] = "error!";
        for (auto & pair : data.table) {
            /* extract signature */
            signature[pair.second] = std::move(QString::fromStdString(pair.first));

            /* extract abbreviation. SEPCIAL THX to @frantic1048 */
            QRegularExpression regex("(~?\\w+|operator(?:\\s*).+)(?=\\(.*\\))");
            QRegularExpressionMatch match = regex.match(signature[pair.second]);
            if (match.hasMatch())
                short_name[pair.second] = std::move(match.captured(1));
            else
                short_name[pair.second] = signature[pair.second];
        }
    }

    auto root = Private::Node
    {
        cg.root.value,
        new QStandardItem,
        Private::Node::child_t()
    };

    {   /* build the tree via BFS */
        QQueue<aop::Node const *>   src_queue;
        QQueue<Private::Node *>     dst_queue;
        src_queue.enqueue(&cg.root);
        dst_queue.enqueue(&root);

        while(!src_queue.empty()) {
            auto src = src_queue.dequeue();
            auto dst = dst_queue.dequeue();

            /* [important]to aovid dst->children resize when push_back
             * Private::Node pointer will be invalid after resize
             */
            dst->children.reserve(src->children.size());
            for (auto & child : src->children) {
                auto fst_item = new QStandardItem(short_name[child.value]);
                auto snd_item = new QStandardItem(signature [child.value]);
                fst_item->setEditable(false);
                snd_item->setEditable(false);

                dst->item->appendRow({fst_item, snd_item});
                dst->children.push_back(Private::Node{
                    child.value,
                    fst_item,
                    Private::Node::child_t()
                });

                if (!child.children.empty()) {
                    src_queue.enqueue(&child);
                    dst_queue.enqueue(&dst->children.back());
                }
            }
        }
    }

    data.tree = new QStandardItemModel(root.item->rowCount(), root.item->columnCount());
    {   /* Set model properties */
        data.tree->setHorizontalHeaderItem(0, new QStandardItem(FileViewHeader1));
        data.tree->setHorizontalHeaderItem(1, new QStandardItem(FileViewHeader2));
        for (auto r = 0, rc = root.item->rowCount(); r < rc; r++)
            for (auto c = 0, cc = root.item->columnCount(); c < cc; c++)
                data.tree->setItem(r, c, root.item->takeChild(r, c));
    }
    delete root.item;
    root.item = nullptr;
    std::swap(data.root, root);

    return std::move(data);
}
Beispiel #11
0
const QString FilePattern::patternFromPath(const QString &path)
{
    if (path.isEmpty())
        return QString();

    static const QRegularExpression MATCH_FILENAME_WITH_FRAME(
            "^"
            "(?<directory>(.*/)?)"
            "(?<baseName>[^.]*)"
            "([.]"
                "("
                    "(?<frame>[0-9.]*?)|"
                    "(?<frameSpec>"
                        "(?<hash>#+)|"
                        "(?<whirl>@+)|"
                        "(?<nuke>%0\\d+d)|"
                        "(?<houdini>($F?<width>(\\d?)))"
                    ")"
                ")"
            ")?"
            "([.]"
                "(?<extension>[^.]*)"
            ")?"
            "$");

    Q_ASSERT(MATCH_FILENAME_WITH_FRAME.isValid());

    QRegularExpressionMatch match = MATCH_FILENAME_WITH_FRAME.match(path);
    if (match.hasMatch()) {
        const QString directory = match.captured("directory");

        const QString baseName = match.captured("baseName");

        QString frameSpec;
        if (!match.captured("frame").isNull()) {
            int width = match.captured("frame").length();
            if (width >= 3 || (width >=1 && match.captured("frame").at(0) == '0')) {
                frameSpec = "%" + QString("0%1d").arg(width);
            } else {
                frameSpec = "%d";
            }
        } else if (!match.captured("hash").isNull()) {
            int width = match.captured("hash").length();
            if (width == 1)
                width = 4;
            frameSpec = "%" + QString("0%1d").arg(width);

        } else if (!match.captured("whirl").isNull()) {
            int width = match.captured("whirl").length();
            frameSpec = "%" + QString("0%1d").arg(width);

        } else if (!match.captured("nuke").isNull()) {
            frameSpec = match.captured("nuke");

        } else if (!match.captured("houdini").isNull()) {
            bool ok;
            int width = match.captured("width").toFloat(&ok);
            if (ok) {
                frameSpec = "%" + QString("0%1d").arg(width);
            }
        }

        const QString extension = match.captured("extension");

        QString pattern;

        if (!directory.isNull())
            pattern += directory;
        if (!baseName.isNull())
            pattern += baseName;
        if (!frameSpec.isNull())
            pattern += "." + frameSpec;
        if (!extension.isNull())
            pattern += "." + extension;

        return pattern;

    } else {
        qWarning() << "couldn't match path" << path;
        return QString();
    }
}
Beispiel #12
0
void PosService::on_btSave_clicked()
{
    QMessageBox box;
    QString fileToCopy = "db.sqlite3";

    QProcess udisks;
    udisks.start("udisks", QStringList() << "--dump");
    if (!udisks.waitForFinished())
    {
        box.setText(_S("Ошибка получения списка дисков udisks --dump"));
        box.exec();
        return;
    }
    QString result = QString::fromUtf8(udisks.readAll());
    QStringList list = result.split(QRegularExpression("={72}"));

    QString interface;
    QString lastProperDevice;
    for(int i=0;i<list.count();++i)
    {
        QRegularExpressionMatch match;
        QString drv = list.at(i);

        if(drv.contains("drive:")){
            interface = "";
            match = QRegularExpression("(?<interface>interface:.*)").match(drv);
            if (!match.hasMatch())
                continue;

            interface = match.captured("interface").mid(10).replace(" ","");

            continue;
        }

        if(interface!="usb")
            continue;

        match = QRegularExpression("(?<device>is mounted:.*)").match(drv);
        if (!match.hasMatch())
            continue;

        QString isMounted = match.captured("device").mid(11).replace(" ","");
        if(isMounted=="1")
            continue;

        match = QRegularExpression("(?<device>device-file:.*)").match(drv);
        if (!match.hasMatch())
            continue;

        lastProperDevice = match.captured("device").mid(12).replace(" ","");

    }

    if(lastProperDevice.isEmpty())
    {
        box.setText(_S("Ошибка - нет подходящего устройства для сохранения"));
        box.exec();
        return;
    }

    udisks.start("udisks", QStringList() << "--mount"<<lastProperDevice<<"/media");
    if (!udisks.waitForFinished())
    {
        box.setText(_S("Ошибка подключения диска udisks --mount %1 /media").arg(lastProperDevice));
        box.exec();
        return;
    }

    QString mountresult = QString::fromUtf8(udisks.readAll());

    QRegularExpressionMatch match = QRegularExpression("(?<device>at .*)").match(mountresult);
    if (!match.hasMatch())
    {
        box.setText(_S("Не удалось обнаружить подключенное устройство\n").arg(mountresult));
        box.exec();
        return;
    }

    QString mountpath = match.captured("device").mid(3).replace(" ","");

    udisks.start("cp", QStringList()<<fileToCopy<<QStringLiteral("%1/db.sqlite").arg(mountpath));
    if (!udisks.waitForFinished())
    {
        box.setText(_S("Не удалось скопировать %1 в %2").arg(fileToCopy).arg(QStringLiteral("%1/db.sqlite").arg(mountpath)));
        box.exec();
        return;
    }

    udisks.start("udisks", QStringList() << "--unmount"<<lastProperDevice);
    if (!udisks.waitForFinished())
    {
        box.setText(_S("Не удалось отключить устройство"));
        box.exec();
        return;
    }

    box.setText(_S("База данных успешно сохранена"));
    box.exec();

    return;

}
Beispiel #13
0
bool genEmoji(QString emoji_in, const QString &emoji_out) {
	QDir d(emoji_in);
	if (!d.exists()) {
		cout << "Could not open emoji input dir '" << emoji_in.toUtf8().constData() << "'!\n";
		QCoreApplication::exit(1);
		return false;
	}
	emoji_in = d.absolutePath() + '/';
	QString emoji_in_200x = d.absolutePath() + "_200x/";
	QDir d_200x(emoji_in_200x);
	if (!d.exists()) {
		cout << "Could not open emoji _200x input dir '" << emoji_in_200x.toUtf8().constData() << "'!\n";
		QCoreApplication::exit(1);
		return false;
	}

	int currentRow = 0, currentColumn = 0;
	uint32 min1 = 0xFFFFFFFF, max1 = 0, min2 = 0xFFFFFFFF, max2 = 0;

	QStringList filters;
    filters << "*.png" << "*.gif";
	QFileInfoList emojis = d.entryInfoList(filters, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
	for (QFileInfoList::const_iterator i = emojis.cbegin(), e = emojis.cend(); i != e; ++i) {
		QString s = i->fileName();
		QRegularExpressionMatch m = QRegularExpression("^([A-F0-9]+)\\.(png|gif)$").match(s);
		if (m.hasMatch()) {
			EmojiData data;
			QString num = m.captured(1);
			if (num.size() != 4 && num.size() != 8 && num.size() != 16) {
				cout << "Bad name found '" << s.toUtf8().constData() << "'!\n";
				continue;
			}

			data.code = ("0x" + num.mid(0, 8)).toUInt(0, 16);
			if (num.size() > 8) {
				data.code2 = ("0x" + num.mid(8)).toUInt(0, 16);
			} else {
				data.code2 = 0;
			}
			data.name = emoji_in + s;
			data.name_200x = emoji_in_200x + s;
			data.x = currentColumn;
			data.y = currentRow;
			++currentColumn;

			if (currentColumn == inRow) {
				++currentRow;
				currentColumn = 0;
			}
			uint32 high = data.code >> 16;
			if (!high) { // small codes
				if (data.code == 169 || data.code == 174) { // two small
				} else {
					if (data.code < min1) min1 = data.code;
					if (data.code > max1) max1 = data.code;
				}
			} else if (high == 35 || high >= 48 && high < 58) { // digits
			} else {
				if (data.code < min2) min2 = data.code;
				if (data.code > max2) max2 = data.code;
			}
			EmojisData::const_iterator i = emojisData.constFind(data.code);
			if (i != emojisData.cend()) {
				cout << QString("Bad emoji code (duplicate) %1 %2 and %3 %4").arg(data.code).arg(data.code2).arg(i->code).arg(i->code2).toUtf8().constData() << "\n";
				continue;
			}
			emojisData.insert(data.code, data);
		} else {
void QgsPropertyOverrideButton::updateSiblingWidgets( bool state )
{
  Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
  {
    switch ( sw.mSiblingType )
    {

      case SiblingCheckState:
      {
        // don't uncheck, only set to checked
        if ( state )
        {
          QAbstractButton *btn = qobject_cast< QAbstractButton * >( sw.mWidgetPointer.data() );
          if ( btn && btn->isCheckable() )
          {
            btn->setChecked( sw.mNatural ? state : !state );
          }
          else
          {
            QGroupBox *grpbx = qobject_cast< QGroupBox * >( sw.mWidgetPointer.data() );
            if ( grpbx && grpbx->isCheckable() )
            {
              grpbx->setChecked( sw.mNatural ? state : !state );
            }
          }
        }
        break;
      }

      case SiblingEnableState:
      {
        QLineEdit *le = qobject_cast< QLineEdit * >( sw.mWidgetPointer.data() );
        if ( le )
          le->setReadOnly( sw.mNatural ? !state : state );
        else
          sw.mWidgetPointer.data()->setEnabled( sw.mNatural ? state : !state );
        break;
      }

      case SiblingVisibility:
      {
        sw.mWidgetPointer.data()->setVisible( sw.mNatural ? state : !state );
        break;
      }

      case SiblingExpressionText:
      {
        QLineEdit *le = qobject_cast<QLineEdit *>( sw.mWidgetPointer.data() );
        if ( le )
        {
          le->setText( mProperty.asExpression() );
        }
        else
        {
          QTextEdit *te = qobject_cast<QTextEdit *>( sw.mWidgetPointer.data() );
          if ( te )
          {
            te->setText( mProperty.asExpression() );
          }
        }
        break;
      }

      case SiblingLinkedWidget:
      {
        if ( QgsColorButton *cb = qobject_cast< QgsColorButton * >( sw.mWidgetPointer.data() ) )
        {
          if ( state && mProperty.isProjectColor() )
          {
            QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) );
            QRegularExpressionMatch match = rx.match( mExpressionString );
            if ( match.hasMatch() )
            {
              cb->linkToProjectColor( match.captured( 1 ) );
            }
          }
          else
          {
            cb->linkToProjectColor( QString() );
          }
        }
        break;
      }
    }
  }
}
void QgsPropertyOverrideButton::updateGui()
{
  bool hasExp = !mExpressionString.isEmpty();
  bool hasField = !mFieldName.isEmpty();

  QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefine.svg" ) );
  QString deftip = tr( "undefined" );
  QString deftype;
  if ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && hasExp )
  {
    icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpression.svg" ) );

    QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) );
    QRegularExpressionMatch match = rx.match( mExpressionString );
    if ( match.hasMatch() )
    {
      icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColorOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColor.svg" ) );
      deftip = match.captured( 1 );
      deftype = tr( "project color" );
    }
    else
    {
      QgsExpression exp( mExpressionString );
      if ( exp.hasParserError() )
      {
        icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionError.svg" ) );
        deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
      }
      else
      {
        deftip = mExpressionString;
      }
    }
  }
  else if ( mProperty.propertyType() != QgsProperty::ExpressionBasedProperty && hasField )
  {
    icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefine.svg" ) );

    if ( !mFieldNameList.contains( mFieldName ) && !mProperty.transformer() )
    {
      icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineError.svg" ) );
      deftip = tr( "'%1' field missing" ).arg( mFieldName );
    }
    else
    {
      deftip = mFieldName;
    }
  }

  setIcon( icon );

  // build full description for tool tip and popup dialog
  mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );

  mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( mProperty.isActive() ? tr( "yes" ) : tr( "no" ) );

  if ( !mUsageInfo.isEmpty() )
  {
    mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
  }

  if ( !mInputDescription.isEmpty() )
  {
    mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
  }

  if ( !mDataTypesString.isEmpty() )
  {
    mFullDescription += tr( "<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
  }

  if ( deftype.isEmpty() && deftip != tr( "undefined" ) )
  {
    deftype = mProperty.propertyType() == QgsProperty::ExpressionBasedProperty ? tr( "expression" ) : tr( "field" );
  }

  // truncate long expressions, or tool tip may be too wide for screen
  if ( deftip.length() > 75 )
  {
    deftip.truncate( 75 );
    deftip.append( QChar( 0x2026 ) );
  }

  mFullDescription += tr( "<b>Current definition (%1):</b><br>%2" ).arg( deftype, deftip );

  setToolTip( mFullDescription );

}