summaryrefslogtreecommitdiff
path: root/src/pmchart/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmchart/main.cpp')
-rw-r--r--src/pmchart/main.cpp742
1 files changed, 742 insertions, 0 deletions
diff --git a/src/pmchart/main.cpp b/src/pmchart/main.cpp
new file mode 100644
index 0000000..93f2acf
--- /dev/null
+++ b/src/pmchart/main.cpp
@@ -0,0 +1,742 @@
+/*
+ * Copyright (c) 2014, Red Hat.
+ * Copyright (c) 2006, Ken McDonell. All Rights Reserved.
+ * Copyright (c) 2007-2009, Aconex. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <QtCore/QSettings>
+#include <QtGui/QStatusBar>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include "main.h"
+#include "openviewdialog.h"
+
+#define DESPERATE 0
+
+int Cflag;
+int Hflag;
+int Lflag;
+int Wflag;
+char *outfile;
+char *outgeometry;
+QFont *globalFont;
+Settings globalSettings;
+
+// Globals used to provide single instances of classes used across pmchart
+GroupControl *liveGroup; // one metrics class group for all hosts
+GroupControl *archiveGroup; // one metrics class group for all archives
+GroupControl *activeGroup; // currently active metric fetchgroup
+TimeControl *pmtime; // one timecontrol class for pmtime
+PmChart *pmchart;
+
+static pmLongOptions longopts[] = {
+ PMAPI_OPTIONS_HEADER("General options"),
+ PMOPT_ALIGN,
+ PMOPT_ARCHIVE,
+ PMOPT_DEBUG,
+ PMOPT_HOST,
+ PMOPT_HOSTSFILE,
+ PMOPT_NAMESPACE,
+ PMOPT_SPECLOCAL,
+ PMOPT_LOCALPMDA,
+ PMOPT_ORIGIN,
+ PMOPT_GUIPORT,
+ PMOPT_START,
+ PMOPT_SAMPLES,
+ PMOPT_FINISH,
+ PMOPT_INTERVAL,
+ PMOPT_TIMEZONE,
+ PMOPT_HOSTZONE,
+ PMOPT_VERSION,
+ PMOPT_HELP,
+ PMAPI_OPTIONS_HEADER("Display options"),
+ { "view", 1, 'c', "VIEW", "chart view(s) to load on startup" },
+ { "check", 0, 'C', 0, "parse views, report any errors and exit" },
+ { "font-size", 1, 'F', "SIZE", "use font of given size" },
+ { "font-family", 1, 'f', "FONT", "use font family" },
+ { "geometry", 1, 'g', "WxH", "image geometry Width x Height" },
+ { "output", 1, 'o', "FILE", "export image to FILE (type from suffix)" },
+ { "samples", 1, 's', "N", "buffer up N points of sample history" },
+ { "visible", 1, 'v', "N", "display N points of visible history" },
+ { "white", 0, 'W', 0, "export images using an opaque (white) background" },
+ PMAPI_OPTIONS_END
+};
+
+// a := a + b for struct timevals
+void tadd(struct timeval *a, struct timeval *b)
+{
+ a->tv_usec += b->tv_usec;
+ if (a->tv_usec > 1000000) {
+ a->tv_usec -= 1000000;
+ a->tv_sec++;
+ }
+ a->tv_sec += b->tv_sec;
+}
+
+//
+// a : b for struct timevals ... <0 for a<b, ==0 for a==b, >0 for a>b
+//
+int tcmp(struct timeval *a, struct timeval *b)
+{
+ int res = (int)(a->tv_sec - b->tv_sec);
+ if (res == 0)
+ res = (int)(a->tv_usec - b->tv_usec);
+ return res;
+}
+
+// convert timeval to seconds
+double tosec(struct timeval t)
+{
+ return t.tv_sec + (t.tv_usec / 1000000.0);
+}
+
+// create a time range in seconds from (delta x points)
+double torange(struct timeval t, int points)
+{
+ return tosec(t) * points;
+}
+
+// conversion from seconds (double precision) to struct timeval
+void fromsec(double value, struct timeval *tv)
+{
+ tv->tv_sec = (time_t)value;
+ tv->tv_usec = (long)(((value - (double)tv->tv_sec) * 1000000.0));
+}
+
+// debugging, display seconds-since-epoch in human readable format
+char *timeString(double seconds)
+{
+ static char string[32];
+ time_t secs = (time_t)seconds;
+ char *s;
+
+ s = pmCtime(&secs, string);
+ s[strlen(s)-1] = '\0';
+ return s;
+}
+
+// return a string containing hour and milliseconds
+char *timeHiResString(double time)
+{
+ static char s[16];
+ char m[8];
+ time_t secs = (time_t)time;
+ struct tm t;
+
+ sprintf(m, "%.3f", time - floor(time));
+ pmLocaltime(&secs, &t);
+ sprintf(s, "%02d:%02d:%02d.%s", t.tm_hour, t.tm_min, t.tm_sec, m+2);
+ s[strlen(s)-1] = '\0';
+ return s;
+}
+
+void nomem(void)
+{
+ // no point trying to report anything ... dump core is the best bet
+ abort();
+}
+
+void setupEnvironment(void)
+{
+ char *value;
+ QString confirm = pmGetConfig("PCP_BIN_DIR");
+ confirm.prepend("PCP_XCONFIRM_PROG=");
+ confirm.append(QChar(__pmPathSeparator()));
+ confirm.append("pmquery");
+ if ((value = strdup((const char *)confirm.toAscii())) != NULL)
+ putenv(value);
+ if (getenv("PCP_STDERR") == NULL && // do not overwrite, for QA
+ ((value = strdup("PCP_STDERR=DISPLAY")) != NULL))
+ putenv(value);
+
+ QCoreApplication::setOrganizationName("PCP");
+ QCoreApplication::setApplicationName(pmProgname);
+}
+
+void writeSettings(void)
+{
+ QSettings userSettings;
+
+ userSettings.beginGroup(pmProgname);
+ if (globalSettings.chartDeltaModified) {
+ globalSettings.chartDeltaModified = false;
+ userSettings.setValue("chartDelta", globalSettings.chartDelta);
+ }
+ if (globalSettings.loggerDeltaModified) {
+ globalSettings.loggerDeltaModified = false;
+ userSettings.setValue("loggerDelta", globalSettings.loggerDelta);
+ }
+ if (globalSettings.sampleHistoryModified) {
+ globalSettings.sampleHistoryModified = false;
+ userSettings.setValue("sampleHistory", globalSettings.sampleHistory);
+ }
+ if (globalSettings.visibleHistoryModified) {
+ globalSettings.visibleHistoryModified = false;
+ userSettings.setValue("visibleHistory", globalSettings.visibleHistory);
+ }
+ if (globalSettings.defaultSchemeModified) {
+ globalSettings.defaultSchemeModified = false;
+ userSettings.setValue("defaultColorScheme",
+ globalSettings.defaultScheme.colorNames());
+ }
+ if (globalSettings.colorSchemesModified) {
+ globalSettings.colorSchemesModified = false;
+ userSettings.beginWriteArray("schemes");
+ for (int i = 0; i < globalSettings.colorSchemes.size(); i++) {
+ userSettings.setArrayIndex(i);
+ userSettings.setValue("name",
+ globalSettings.colorSchemes[i].name());
+ userSettings.setValue("colors",
+ globalSettings.colorSchemes[i].colorNames());
+ }
+ userSettings.endArray();
+ }
+ if (globalSettings.chartBackgroundModified) {
+ globalSettings.chartBackgroundModified = false;
+ userSettings.setValue("chartBackgroundColor",
+ globalSettings.chartBackgroundName);
+ }
+ if (globalSettings.chartHighlightModified) {
+ globalSettings.chartHighlightModified = false;
+ userSettings.setValue("chartHighlightColor",
+ globalSettings.chartHighlightName);
+ }
+ if (globalSettings.initialToolbarModified) {
+ globalSettings.initialToolbarModified = false;
+ userSettings.setValue("initialToolbar", globalSettings.initialToolbar);
+ }
+ if (globalSettings.nativeToolbarModified) {
+ globalSettings.nativeToolbarModified = false;
+ userSettings.setValue("nativeToolbar", globalSettings.nativeToolbar);
+ }
+ if (globalSettings.toolbarLocationModified) {
+ globalSettings.toolbarLocationModified = false;
+ userSettings.setValue("toolbarLocation",
+ globalSettings.toolbarLocation);
+ }
+ if (globalSettings.toolbarActionsModified) {
+ globalSettings.toolbarActionsModified = false;
+ userSettings.setValue("toolbarActions", globalSettings.toolbarActions);
+ }
+ if (globalSettings.fontFamilyModified) {
+ globalSettings.fontFamilyModified = false;
+ if (globalSettings.fontFamily != QString(PmChart::defaultFontFamily()))
+ userSettings.setValue("fontFamily", globalSettings.fontFamily);
+ else
+ userSettings.remove("fontFamily");
+ }
+ if (globalSettings.fontStyleModified) {
+ globalSettings.fontStyleModified = false;
+ if (globalSettings.fontStyle != QString("Normal"))
+ userSettings.setValue("fontStyle", globalSettings.fontStyle);
+ else
+ userSettings.remove("fontStyle");
+ }
+ if (globalSettings.fontSizeModified) {
+ globalSettings.fontSizeModified = false;
+ if (globalSettings.fontSize != PmChart::defaultFontSize())
+ userSettings.setValue("fontSize", globalSettings.fontSize);
+ else
+ userSettings.remove("fontSize");
+ }
+ if (globalSettings.savedHostsModified) {
+ globalSettings.savedHostsModified = false;
+ if (globalSettings.savedHosts.isEmpty() == false)
+ userSettings.setValue("savedHosts", globalSettings.savedHosts);
+ else
+ userSettings.remove("savedHosts");
+ }
+
+ userSettings.endGroup();
+}
+
+void checkHistory(int samples, int visible)
+{
+ // sanity checking on sample sizes
+ if (samples < PmChart::minimumPoints()) {
+ globalSettings.sampleHistory = PmChart::minimumPoints();
+ globalSettings.sampleHistoryModified = true;
+ }
+ if (samples > PmChart::maximumPoints()) {
+ globalSettings.sampleHistory = PmChart::maximumPoints();
+ globalSettings.sampleHistoryModified = true;
+ }
+ if (visible < PmChart::minimumPoints()) {
+ globalSettings.visibleHistory = PmChart::minimumPoints();
+ globalSettings.visibleHistoryModified = true;
+ }
+ if (visible > PmChart::maximumPoints()) {
+ globalSettings.visibleHistory = PmChart::maximumPoints();
+ globalSettings.visibleHistoryModified = true;
+ }
+ if (samples < visible) {
+ globalSettings.sampleHistory = globalSettings.visibleHistory;
+ globalSettings.sampleHistoryModified = true;
+ }
+}
+
+static void readSettings(void)
+{
+ QSettings userSettings;
+ userSettings.beginGroup(pmProgname);
+
+ //
+ // Parameters related to sampling
+ //
+ globalSettings.chartDeltaModified = false;
+ globalSettings.chartDelta = userSettings.value("chartDelta",
+ PmChart::defaultChartDelta()).toDouble();
+ globalSettings.loggerDeltaModified = false;
+ globalSettings.loggerDelta = userSettings.value("loggerDelta",
+ PmChart::defaultLoggerDelta()).toDouble();
+ globalSettings.sampleHistoryModified = false;
+ globalSettings.sampleHistory = userSettings.value("sampleHistory",
+ PmChart::defaultSampleHistory()).toInt();
+ globalSettings.visibleHistoryModified = false;
+ globalSettings.visibleHistory = userSettings.value("visibleHistory",
+ PmChart::defaultVisibleHistory()).toInt();
+ checkHistory(globalSettings.sampleHistory, globalSettings.visibleHistory);
+ if (globalSettings.sampleHistoryModified) {
+ userSettings.setValue("samplePoints", globalSettings.sampleHistory);
+ globalSettings.sampleHistoryModified = false;
+ }
+ if (globalSettings.visibleHistoryModified) {
+ userSettings.setValue("visiblePoints", globalSettings.visibleHistory);
+ globalSettings.visibleHistoryModified = false;
+ }
+
+ //
+ // Everything colour (scheme) related
+ //
+ QStringList colorList;
+ globalSettings.defaultSchemeModified = false;
+ if (userSettings.contains("defaultColorScheme") == true)
+ colorList = userSettings.value("defaultColorScheme").toStringList();
+ else
+ colorList
+ << "#ffff00" << "#0000ff" << "#ff0000" << "#008000" << "#ee82ee"
+ << "#aa5500" << "#666666" << "#aaff00" << "#aa00ff" << "#aaaa7f";
+ globalSettings.defaultScheme.setName("#-cycle");
+ globalSettings.defaultScheme.setModified(false);
+ globalSettings.defaultScheme.setColorNames(colorList);
+
+ int size = userSettings.beginReadArray("schemes");
+ for (int i = 0; i < size; i++) {
+ userSettings.setArrayIndex(i);
+ ColorScheme scheme;
+ scheme.setName(userSettings.value("name").toString());
+ scheme.setModified(false);
+ scheme.setColorNames(userSettings.value("colors").toStringList());
+ globalSettings.colorSchemes.append(scheme);
+ }
+ userSettings.endArray();
+
+ //
+ // Everything (else) colour related
+ //
+ globalSettings.chartBackgroundModified = false;
+ globalSettings.chartBackgroundName = userSettings.value(
+ "chartBackgroundColor", "#6ca2c9").toString();
+ globalSettings.chartBackground = QColor(globalSettings.chartBackgroundName);
+
+ globalSettings.chartHighlightModified = false;
+ globalSettings.chartHighlightName = userSettings.value(
+ "chartHighlightColor", "blue").toString();
+ globalSettings.chartHighlight = QColor(globalSettings.chartHighlightName);
+
+ //
+ // Toolbar user preferences
+ //
+ globalSettings.initialToolbarModified = false;
+ globalSettings.initialToolbar = userSettings.value(
+ "initialToolbar", 1).toInt();
+ globalSettings.nativeToolbarModified = false;
+ globalSettings.nativeToolbar = userSettings.value(
+ "nativeToolbar", 1).toInt();
+ globalSettings.toolbarLocationModified = false;
+ globalSettings.toolbarLocation = userSettings.value(
+ "toolbarLocation", 0).toInt();
+ QStringList actionList;
+ globalSettings.toolbarActionsModified = false;
+ if (userSettings.contains("toolbarActions") == true)
+ globalSettings.toolbarActions =
+ userSettings.value("toolbarActions").toStringList();
+ // else: (defaults come from the pmchart.ui interface specification)
+
+ //
+ // Font preferences
+ //
+ globalSettings.fontFamilyModified = false;
+ globalSettings.fontFamily = userSettings.value(
+ "fontFamily", PmChart::defaultFontFamily()).toString();
+ globalSettings.fontStyleModified = false;
+ QString fontStyle;
+ globalSettings.fontStyle = userSettings.value(
+ "fontStyle", "Normal").toString();
+ globalSettings.fontSizeModified = false;
+ globalSettings.fontSize = userSettings.value(
+ "fontSize", PmChart::defaultFontSize()).toInt();
+
+ //
+ // Saved Hosts list preferences
+ //
+ globalSettings.savedHostsModified = false;
+ if (userSettings.contains("savedHosts") == true)
+ globalSettings.savedHosts =
+ userSettings.value("savedHosts").toStringList();
+
+ userSettings.endGroup();
+}
+
+static void readSchemes(void)
+{
+ QChar sep(__pmPathSeparator());
+ QString schemes = pmGetConfig("PCP_VAR_DIR");
+ schemes.append(sep).append("config");
+ schemes.append(sep).append("pmchart");
+ schemes.append(sep).append("Schemes");
+
+ QFileInfo fi(schemes);
+ if (fi.exists())
+ OpenViewDialog::openView(schemes.toAscii());
+}
+
+// Get next color from given scheme or from default colors for #-cycle
+QColor nextColor(QString scheme, int *sequence)
+{
+ QList<QColor> colorList;
+ int seq = (*sequence)++;
+
+ for (int i = 0; i < globalSettings.colorSchemes.size(); i++) {
+ if (globalSettings.colorSchemes[i].name() == scheme) {
+ colorList = globalSettings.colorSchemes[i].colors();
+ break;
+ }
+ }
+ if (colorList.size() < 2) // common case
+ colorList = globalSettings.defaultScheme.colors();
+ if (colorList.size() < 2) // idiot user!?
+ colorList << QColor("yellow") << QColor("blue") << QColor("red")
+ << QColor("green") << QColor("violet");
+ seq %= colorList.size();
+ return colorList.at(seq);
+}
+
+static void setupViewGlobals()
+{
+ int w, h, points, x, y;
+
+ OpenViewDialog::globals(&w, &h, &points, &x, &y);
+ if (w || h) {
+ QSize size = pmchart->size().expandedTo(QSize(w, h));
+ QSize desk = QApplication::desktop()->availableGeometry().size();
+ pmchart->resize(size.boundedTo(desk));
+ }
+ if (x || y) {
+ QPoint pos = pmchart->pos();
+ if (x) pos.setX(x);
+ if (y) pos.setY(y);
+ pmchart->move(pos);
+ }
+ if (points) {
+ if (activeGroup->sampleHistory() < points)
+ activeGroup->setSampleHistory(points);
+ activeGroup->setVisibleHistory(points);
+ }
+}
+
+static int
+override(int opt, pmOptions *opts)
+{
+ (void)opts;
+ if (opt == 'g')
+ return 1;
+ if (opt == 'H')
+ Hflag = 1;
+ if (opt == 'L')
+ Lflag = 1;
+ return 0;
+}
+
+int
+main(int argc, char ** argv)
+{
+ int c, sts;
+ int sh = -1; /* sample history length */
+ int vh = -1; /* visible history length */
+ char *endnum;
+ Tab *tab;
+ struct timeval logStartTime;
+ struct timeval logEndTime;
+ QStringList configs;
+ QString tzLabel;
+ QString tzString;
+ pmOptions opts;
+
+ memset(&opts, 0, sizeof(opts));
+ __pmtimevalNow(&opts.origin);
+ __pmSetProgname(argv[0]);
+ QApplication a(argc, argv);
+ setupEnvironment();
+ readSettings();
+
+ opts.flags = PM_OPTFLAG_MULTI | PM_OPTFLAG_MIXED;
+ opts.short_options = "A:a:Cc:D:f:F:g:h:H:Ln:o:O:p:s:S:T:t:Vv:WzZ:?";
+ opts.long_options = longopts;
+ opts.short_usage = "[options] [sources]";
+ opts.override = override;
+
+
+ while ((c = pmGetOptions(argc, argv, &opts)) != EOF) {
+ switch (c) {
+
+ case 'C':
+ Cflag++;
+ break;
+
+ case 'c':
+ configs.append(opts.optarg);
+ break;
+
+ case 'f':
+ globalSettings.fontFamily = opts.optarg;
+ break;
+
+ case 'F':
+ sts = (int)strtol(opts.optarg, &endnum, 10);
+ if (*endnum != '\0' || c < 0) {
+ pmprintf("%s: -F requires a numeric argument\n", pmProgname);
+ opts.errors++;
+ } else {
+ globalSettings.fontSize = sts;
+ }
+ break;
+
+ case 'g':
+ outgeometry = opts.optarg;
+ break;
+
+ case 'o': /* output image file */
+ outfile = opts.optarg;
+ break;
+
+ case 'W': /* white image background */
+ Wflag = 1;
+ break;
+
+ case 'v': /* visible history */
+ vh = (int)strtol(opts.optarg, &endnum, 10);
+ if (*endnum != '\0' || vh < 1) {
+ pmprintf("%s: -v requires a numeric argument, larger than 1\n",
+ pmProgname);
+ opts.errors++;
+ }
+ break;
+ }
+ }
+
+ /* hosts from a Hosts file are added to the SavedHosts list */
+ if (Hflag) {
+ for (int i = 0; i < opts.nhosts; i++)
+ globalSettings.savedHosts.append(opts.hosts[i]);
+ globalSettings.savedHostsModified = true;
+ }
+
+ if (opts.narchives > 0) {
+ while (opts.optind < argc)
+ __pmAddOptArchive(&opts, argv[opts.optind++]);
+ } else {
+ if (!Hflag) {
+ for (c = 0; c < globalSettings.savedHosts.size(); c++) {
+ const QString &host = globalSettings.savedHosts.at(c);
+ __pmAddOptHost(&opts, (char *)(const char *)host.toAscii());
+ }
+ }
+ while (opts.optind < argc)
+ __pmAddOptHost(&opts, argv[opts.optind++]);
+ }
+
+ if (opts.optind != argc)
+ opts.errors++;
+ if (opts.errors) {
+ pmUsageMessage(&opts);
+ exit(1);
+ }
+
+ /* set initial sampling interval from command line, else global setting */
+ if (opts.interval.tv_sec == 0 && opts.interval.tv_usec == 0)
+ fromsec(globalSettings.chartDelta, &opts.interval);
+
+ console = new QedConsole(opts.origin);
+
+ //
+ // Deal with user requested sample/visible points globalSettings. These
+ // (command line) override the QSettings values, for this instance
+ // of pmchart. They should not be written though, unless requested
+ // later via the Settings dialog.
+ //
+ sh = opts.samples ? opts.samples : -1;
+ if (vh != -1 || sh != -1) {
+ if (sh == -1)
+ sh = globalSettings.sampleHistory;
+ if (vh == -1)
+ vh = globalSettings.visibleHistory;
+ checkHistory(sh, vh);
+ if (globalSettings.sampleHistoryModified ||
+ globalSettings.visibleHistoryModified) {
+ pmprintf("%s: invalid sample/visible history\n", pmProgname);
+ pmflush();
+ exit(1);
+ }
+ globalSettings.sampleHistory = sh;
+ globalSettings.visibleHistory = vh;
+ }
+ console->post("Global settings setup complete");
+
+ // Create all of the sources
+ liveGroup = new GroupControl();
+ archiveGroup = new GroupControl();
+ if (Lflag)
+ liveGroup->use(PM_CONTEXT_LOCAL, QmcSource::localHost);
+ sts = opts.nhosts + opts.narchives;
+ for (c = 0; c < opts.nhosts; c++)
+ if (liveGroup->use(PM_CONTEXT_HOST, opts.hosts[c]) < 0)
+ sts--;
+ for (c = 0; c < opts.narchives; c++)
+ if (archiveGroup->use(PM_CONTEXT_ARCHIVE, opts.archives[c]) < 0)
+ sts--;
+ if (Lflag == 0 && sts == 0)
+ liveGroup->createLocalContext();
+ pmflush();
+ console->post("Metric group setup complete (%d hosts, %d archives)",
+ opts.nhosts, opts.narchives);
+
+ if (opts.tzflag) {
+ if (opts.narchives > 0)
+ archiveGroup->useTZ();
+ if (opts.nhosts > 0)
+ liveGroup->useTZ();
+ }
+ else if (opts.timezone != NULL) {
+ if (opts.narchives > 0)
+ archiveGroup->useTZ(QString(opts.timezone));
+ if (opts.nhosts > 0)
+ liveGroup->useTZ(QString(opts.timezone));
+ if ((sts = pmNewZone(opts.timezone)) < 0) {
+ pmprintf("%s: cannot set timezone to \"%s\": %s\n",
+ pmProgname, (char *)opts.timezone, pmErrStr(sts));
+ pmflush();
+ exit(1);
+ }
+ }
+
+ //
+ // Choose which Tab will be displayed initially - archive/live.
+ // If any archives given on command line, we go Archive mode;
+ // otherwise Live mode wins. Our initial pmtime connection is
+ // set in that mode too. Later we'll make a second connection
+ // in the other mode (and only "on-demand").
+ //
+ if (opts.narchives > 0) {
+ archiveGroup->defaultTZ(tzLabel, tzString);
+ archiveGroup->updateBounds();
+ logStartTime = archiveGroup->logStart();
+ logEndTime = archiveGroup->logEnd();
+ if ((sts = pmParseTimeWindow(opts.start_optarg, opts.finish_optarg,
+ opts.align_optarg, opts.origin_optarg,
+ &logStartTime, &logEndTime, &opts.start,
+ &opts.finish, &opts.origin, &endnum)) < 0) {
+ pmprintf("Cannot parse archive time window\n%s\n", endnum);
+ pmUsageMessage(&opts);
+ free(endnum);
+ exit(1);
+ }
+ // move position to account for initial visible points
+ if (tcmp(&opts.origin, &opts.start) <= 0)
+ for (c = 0; c < globalSettings.visibleHistory - 2; c++)
+ tadd(&opts.origin, &opts.interval);
+ if (tcmp(&opts.origin, &opts.finish) > 0)
+ opts.origin = opts.finish;
+ }
+ else {
+ liveGroup->defaultTZ(tzLabel, tzString);
+ __pmtimevalNow(&logStartTime);
+ logEndTime.tv_sec = logEndTime.tv_usec = INT_MAX;
+ if ((sts = pmParseTimeWindow(opts.start_optarg, opts.finish_optarg,
+ opts.align_optarg, opts.origin_optarg,
+ &logStartTime, &logEndTime, &opts.start,
+ &opts.finish, &opts.origin, &endnum)) < 0) {
+ pmprintf("Cannot parse live time window\n%s\n", endnum);
+ pmUsageMessage(&opts);
+ free(endnum);
+ exit(1);
+ }
+ }
+ console->post("Timezones and time window setup complete");
+
+ globalFont = new QFont(globalSettings.fontFamily, globalSettings.fontSize);
+ if (globalSettings.fontStyle.contains("Italic"))
+ globalFont->setItalic(true);
+ if (globalSettings.fontStyle.contains("Bold"))
+ globalFont->setBold(true);
+
+ tab = new Tab;
+ fileIconProvider = new QedFileIconProvider();
+
+ pmchart = new PmChart;
+ pmtime = new TimeControl;
+
+ console->post("Phase1 user interface constructors complete");
+
+ // Start pmtime process for time management
+ pmtime->init(opts.guiport, opts.narchives == 0, &opts.interval, &opts.origin,
+ &opts.start, &opts.finish, tzString, tzLabel);
+
+ pmchart->init();
+ liveGroup->init(globalSettings.sampleHistory,
+ globalSettings.visibleHistory,
+ pmtime->liveInterval(), pmtime->livePosition());
+ archiveGroup->init(globalSettings.sampleHistory,
+ globalSettings.visibleHistory,
+ pmtime->archiveInterval(), pmtime->archivePosition());
+
+ //
+ // We setup the pmchart tab list late, so we don't have to deal
+ // with pmtime messages reaching the Tabs until we're all setup.
+ //
+ if (opts.narchives == 0)
+ tab->init(pmchart->tabWidget(), liveGroup, "Live");
+ else
+ tab->init(pmchart->tabWidget(), archiveGroup, "Archive");
+ pmchart->tabWidget()->insertTab(tab);
+ pmchart->setActiveTab(0, true);
+ console->post("Phase2 user interface setup complete");
+
+ readSchemes();
+ for (c = 0; c < configs.size(); c++)
+ if (!OpenViewDialog::openView((const char *)configs[c].toAscii()))
+ opts.errors++;
+ if (opts.errors)
+ exit(1);
+ setupViewGlobals();
+ pmflush();
+
+ if (Cflag) // done with -c config, quit
+ return 0;
+
+ pmchart->enableUi();
+ pmchart->show();
+ console->post("Top level window shown");
+
+ a.connect(&a, SIGNAL(lastWindowClosed()), pmchart, SLOT(quit()));
+ return a.exec();
+}