1 Star 2 Fork 1

GXDE OS/garma

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Garma.cpp 82.65 KB
一键复制 编辑 原始数据 按行查看 历史
gfdgd xi 提交于 2025-01-27 13:37 +08:00 . garma任务栏图标不再显示系统默认图标
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016
/*
* Garma - a Zenity clone for Qt4 and Qt5
* Copyright 2014 by Thomas Lübking <thomas.luebking@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
*
* 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
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Garma.h"
#include "define_global.h"
#include <QHeaderView>
#include <iostream>
#include <QAction>
#include <QBoxLayout>
#include <QCalendarWidget>
#include <QCheckBox>
#include <QColorDialog>
#include <QComboBox>
#include <QDate>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDialogButtonBox>
#include <QEvent>
#include <DFileDialog>
#include <QFontDialog>
#include <QFormLayout>
#include <QIcon>
#include <QInputDialog>
#include <QLabel>
#include <QLocale>
#include <QLineEdit>
#include <QMessageBox>
#include <QProcess>
#include <QProgressDialog>
#include <QPropertyAnimation>
#include <QPushButton>
#include <QScreen>
#include <QScrollBar>
#include <QSettings>
#include <QSlider>
#include <QSocketNotifier>
#include <QStringBuilder>
#include <QStringList>
#include <QTextBrowser>
#include <QTimer>
#include <QTimerEvent>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <dmainwindow.h>
#include <ddialog.h>
#include <DApplication>
#include <dinputdialog.h>
#include "inputguard.h"
#include "gmessagebox.h"
#include "gprogressdialog.h"
#include "dfiledialog.h"
#include "dimagebutton.h"
#include "dialogmanager.h"
#if QT_VERSION >= 0x050000
// this is to hack access to the --title parameter in Qt5
#include <QWindow>
#endif
#include <QtDebug>
#include <cfloat>
#ifdef Q_OS_UNIX
#include <signal.h>
#include <unistd.h>
#endif
InputGuard *InputGuard::s_instance = NULL;
#ifdef WS_X11
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
#include <QGuiApplication>
#else
#include <QX11Info>
#endif
#include <X11/Xlib.h>
#endif
typedef QPair<QString, QString> Help;
typedef QList<Help> HelpList;
typedef QPair<QString, HelpList> CategoryHelp;
typedef QMap<QString, CategoryHelp> HelpDict;
Garma::Garma(int &argc, char **argv) : DApplication(argc, argv)
, m_modal(false)
, m_selectableLabel(false)
, m_popup(false)
, m_parentWindow(0)
, m_timeout(0)
, m_notificationId(0)
, m_dialog(NULL)
, m_type(Invalid)
{
// 加载翻译
this->loadTranslator();
m_pos = QPoint(INT_MAX, INT_MAX); // invalid
QStringList argList = QCoreApplication::arguments(); // arguments() is slow
const QString binary = argList.at(0);
m_zenity = binary.endsWith("zenity");
// make canonical list
QStringList args;
if (argList.at(0).endsWith("-askpass")) {
argList.removeFirst();
args << "--title" << tr("Enter Password") << "--password" << "--prompt" << argList.join(' ');
} else {
for (int i = 1; i < argList.count(); ++i) {
if (argList.at(i).startsWith("--")) {
int split = argList.at(i).indexOf('=');
if (split > -1) {
args << argList.at(i).left(split) << argList.at(i).mid(split+1);
} else {
args << argList.at(i);
}
} else {
args << argList.at(i);
}
}
}
argList.clear();
if (!readGeneral(args))
return;
// set application class
if (!m_class.isNull())
QCoreApplication::setApplicationName(m_class);
// set application name
if (!m_name.isNull())
// Qt intercepts "--name name" but fails to process "--name=name"
// Workaround this by setting the RESOURCE_NAME environment variable
// which ends up being used to populate the WM_CLASS name on X11.
qputenv("RESOURCE_NAME", m_name.toLocal8Bit());
// 创建一个不显示的 DMainWindow 以便能正常显示对话框
DMainWindow *window = new DMainWindow();
window->hide();
char error = 1;
foreach (const QString &arg, args) {
if (arg == "--calendar") {
m_type = Calendar;
error = showCalendar(args);
} else if (arg == "--entry") {
m_type = Entry;
error = showEntry(args);
} else if (arg == "--error") {
m_type = Error;
error = showMessage(args, 'e');
} else if (arg == "--info") {
m_type = Info;
error = showMessage(args, 'i');
} else if (arg == "--file-selection") {
m_type = FileSelection;
error = showFileSelection(args);
} else if (arg == "--list") {
m_type = List;
error = showList(args);
} else if (arg == "--notification") {
m_type = Notification;
error = showNotification(args);
} else if (arg == "--progress") {
m_type = Progress;
error = showProgress(args);
} else if (arg == "--question") {
m_type = Question;
error = showMessage(args, 'q');
} else if (arg == "--warning") {
m_type = Warning;
error = showMessage(args, 'w');
} else if (arg == "--scale") {
m_type = Scale;
error = showScale(args);
} else if (arg == "--text-info") {
m_type = TextInfo;
error = showText(args);
} else if (arg == "--color-selection") {
m_type = ColorSelection;
error = showColorSelection(args);
} else if (arg == "--font-selection") {
m_type = FontSelection;
error = showFontSelection(args);
} else if (arg == "--password") {
m_type = Password;
error = showPassword(args);
} else if (arg == "--forms") {
m_type = Forms;
error = showForms(args);
} else if (arg == "--dzen") {
m_type = Dzen;
error = showDzen(args);
} else if (arg == "--about") {
m_type = About;
error = showAbout(args);
}
if (error != 1) {
break;
}
}
if (error) {
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
return;
}
if (m_dialog) {
#if QT_VERSION >= 0x050000
/* Stage #1 one of "Setting a window title should be easy but Qt5 is dumb"
Qt5 sucks away "--title foo" but not "--title=foo" and then stumbles
over itself when trying to set it
So #1 we seek to get ourselfs access to the window title to get some
control over it
since it's set on showing the first QWindow, we just create one here
and copy the title
*/
/// @todo: remove once this is fixed in Qt5 - ie. "never"
const bool qt5title = m_caption.isNull(); // otherwise we read it in the general options
if (qt5title) {
QWindow *w = new QWindow;
w->setVisible(true);
m_caption = w->title();
delete w;
m_dialog->setWindowTitle("");
}
m_dialog->setWindowTitle(m_caption);
// so much for stage one, see below for more on Qt5 being dumb...
#endif
// close on ctrl+return in addition to ctrl+enter
QAction *shortAccept = new QAction(m_dialog);
m_dialog->addAction(shortAccept);
QList<QKeySequence> cuts;
cuts << QKeySequence(Qt::CTRL|Qt::Key_Return) << QKeySequence(Qt::CTRL|Qt::Key_Enter);
shortAccept->setShortcuts(cuts);
connect (shortAccept, SIGNAL(triggered()), m_dialog, SLOT(accept()));
// workaround for #21 - since QWidget is now merely bitrot, QDialog closes,
// but does not reject on the escape key (unlike announced in the specific section of the API)
QAction *shortReject = new QAction(m_dialog);
m_dialog->addAction(shortReject);
shortReject->setShortcut(QKeySequence(Qt::Key_Escape));
connect (shortReject, SIGNAL(triggered()), m_dialog, SLOT(reject()));
if (!m_size.isNull()) {
m_dialog->adjustSize();
//DDialog *dl = static_cast<DDialog*>(m_dialog);
QSize sz = m_dialog->size();
if (m_size.width() > 0)
sz.setWidth(m_size.width());
if (m_size.height() > 0)
sz.setHeight(m_size.height());
m_dialog->resize(sz);
}
if (m_pos.x() < INT_MAX) {
QRect desktop = QGuiApplication::screens().at(0)->availableGeometry();
if (m_pos.x() < 0)
m_pos.rx() = desktop.right() + m_pos.x() - m_dialog->width();
if (m_pos.y() < 0)
m_pos.ry() = desktop.bottom() + m_pos.y() - m_dialog->height();
m_dialog->move(m_pos);
}
m_dialog->setWindowModality(m_modal ? Qt::ApplicationModal : Qt::NonModal);
/* Stage #2 one of "Setting a window title should be easy but Qt5 is dumb"
Errhemmm... Fuck! This! Shit!
Not only is Qt5 too dumb to set the window title by parameter, if one
does it, at least on X11 Qt5 doesn't set the property on the platform
window *before* mapping it, but *while* - causing an IPC race condition
with the WMs that will pick up the "old" title, but also miss the property
update because it can happen while they're configuring the window.
Awesome.
Because we can't retroactively preceed the mapping, we at least need to
make sure that the title gets updated after the window is mapped and
configured - what we can only guess witha timer... *grrrrr*
Since setting the same title is idempotent and skipped in ::setWindowTitle
(what would be great if the entire thing wasn't broken to begin with)
We need two steps to first clear and second reset the title - maximzing
the server roundtrips...
But hey, abstract and wayland and QML... FUCK! THIS! SHIT! *grrrrrrrr*
*/
// We do this after the dialog creation, because the setup can take varying times
if (!(m_caption.isNull() || binary.endsWith(m_caption)))
QTimer::singleShot(10, this, [=]() {m_dialog->setWindowTitle(""); m_dialog->setWindowTitle(m_caption);});
// so much for setting the window title - despite Qt trying to do it by itself
if (!m_icon.isNull())
m_dialog->setWindowIcon(QIcon(m_icon));
QDialogButtonBox *box = m_dialog->findChild<QDialogButtonBox*>();
if (box && !m_ok.isNull()) {
if (QPushButton *btn = box->button(QDialogButtonBox::Ok))
btn->setText(m_ok);
}
if (box && !m_cancel.isNull()) {
if (QPushButton *btn = box->button(QDialogButtonBox::Cancel))
btn->setText(m_cancel);
}
if (m_parentWindow) {
#ifdef WS_X11
m_dialog->setAttribute(Qt::WA_X11BypassTransientForHint);
Display *dpy;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
dpy = QGuiApplication::nativeInterface<QNativeInterface::QX11Application>()->display();
#else
dpy = QX11Info::display();
#endif
XSetTransientForHint(dpy, m_dialog->winId(), m_parentWindow);
#endif
}
}
}
void Garma::setDialogIconWithStandard(int index, QDialog *dialog)
{
auto icon = (enum QStyle::StandardPixmap)index;
dialog->setWindowIcon(DApplication::style()->standardIcon(icon));
}
bool Garma::error(const QString message)
{
printf("Error: %s", qPrintable(message));
QMetaObject::invokeMethod(this, "quitOnError", Qt::QueuedConnection);
return true;
}
static QString value(const QWidget *w, const QString &pattern)
{
if (!w)
return QString();
IF_IS(QLineEdit) {
return t->text();
} else IF_IS(QTreeWidget) {
QString s;
foreach (QTreeWidgetItem *item, t->selectedItems()) {
for (int i = 0; i < t->columnCount(); ++i)
s += item->text(i);
}
return s;
} else IF_IS(QComboBox) {
return t->currentText();
} else IF_IS(QCalendarWidget) {
if (pattern.isNull())
return QLocale::system().toString(t->selectedDate(), QLocale::ShortFormat);
return t->selectedDate().toString(pattern);
} else IF_IS(QCheckBox) {
return t->isChecked() ? "true" : "false";
}
return QString();
}
void Garma::dialogFinished(int status)
{
if (m_type == FileSelection) {
DFileDialog *dlg = static_cast<DFileDialog*>(sender());
QVariantList l;
for (int i = 0; i < dlg->sidebarUrls().count(); ++i)
l << dlg->sidebarUrls().at(i);
QSettings settings("Garma");
settings.setValue("Bookmarks", l);
settings.setValue("FileDetails", dlg->viewMode() == DFileDialog::Detail);
}
if (!(status == QDialog::Accepted || status == GMessageBox::Ok || status == GMessageBox::Yes)) {
#ifdef Q_OS_UNIX
if (sender()->property("Garma_autokill_parent").toBool()) {
::kill(getppid(), 9); // 使用 9 可以强制关闭进程
// 等效于 kill -9 xxx
}
#endif
exit(1);
return;
}
switch (m_type) {
case Question:
case Warning:
case Info:
case Error:
case Progress:
case Notification:
break;
case Calendar: {
QString format = sender()->property("Garma_date_format").toString();
QDate date = sender()->findChild<QCalendarWidget*>()->selectedDate();
if (format.isEmpty())
printf("%s\n", qPrintable(QLocale::system().toString(date, QLocale::ShortFormat)));
else
printf("%s\n", qPrintable(date.toString(format)));
break;
}
case Entry: {
DInputDialog *dlg = static_cast<DInputDialog*>(sender());
if (dlg->inputMode() == DInputDialog::DoubleInput) {
printf("%s\n", qPrintable(QLocale::c().toString(dlg->doubleValue(), 'f', 2)));
} else if (dlg->inputMode() == DInputDialog::IntInput) {
printf("%d\n", dlg->intValue());
} else {
printf("%s\n", qPrintable(dlg->textValue()));
}
break;
}
case Password: {
QLineEdit *username = sender()->findChild<QLineEdit*>("Garma_username"),
*password = sender()->findChild<QLineEdit*>("Garma_password");
QString result;
if (username)
result = username->text() + '|';
if (password)
result += password->text();
printf("%s\n", qPrintable(result));
break;
}
case FileSelection: {
QStringList files = static_cast<DFileDialog*>(sender())->selectedFiles();
printf("%s\n", qPrintable(files.join(sender()->property("Garma_separator").toString())));
break;
}
case ColorSelection: {
QColorDialog *dlg = static_cast<QColorDialog*>(sender());
printf("%s\n", qPrintable(dlg->selectedColor().name()));
QVariantList l;
for (int i = 0; i < dlg->customCount(); ++i)
l << dlg->customColor(i).rgba();
QSettings("Garma").setValue("CustomPalette", l);
break;
}
case FontSelection: {
QFontDialog *dlg = static_cast<QFontDialog*>(sender());
QFont fnt = dlg->selectedFont();
int size = fnt.pointSize();
if (size < 0)
size = fnt.pixelSize();
// crude mapping of Qt's random enum to xft's random category
QString weight = "medium";
if (fnt.weight() < 35) weight = "light";
else if (fnt.weight() > 85) weight = "black";
else if (fnt.weight() > 70) weight = "bold";
else if (fnt.weight() > 60) weight = "demibold";
QString slant = "roman";
if (fnt.style() == QFont::StyleItalic) slant = "italic";
else if (fnt.style() == QFont::StyleOblique) slant = "oblique";
QString font = sender()->property("Garma_fontpattern").toString();
font = font.arg(fnt.family()).arg(size).arg(weight).arg(slant);
printf("%s\n", qPrintable(font));
break;
}
case TextInfo: {
QTextEdit *te = sender()->findChild<QTextEdit*>();
if (te && !te->isReadOnly()) {
printf("%s\n", qPrintable(te->toPlainText()));
}
break;
}
case Scale: {
QSlider *sld = sender()->findChild<QSlider*>();
if (sld) {
printf("%s\n", qPrintable(QString::number(sld->value())));
}
break;
}
case List: {
QTreeWidget *tw = sender()->findChild<QTreeWidget*>();
QStringList result;
if (tw && m_listPrintColumn == -1) {
bool done(false);
if (m_listCheckable) {
for (int i = 0; i < tw->topLevelItemCount(); ++i) {
const QTreeWidgetItem *twi = tw->topLevelItem(i);
if (twi->checkState(0) == Qt::Checked)
result << twi->text(1);
}
}
else {
foreach (const QTreeWidgetItem *twi, tw->selectedItems()) {
result << twi->text(0);
}
}
}
else if (tw && m_listPrintColumn >= 0) {
if (m_listCheckable) {
for (int i = 0; i < tw->topLevelItemCount(); ++i) {
const QTreeWidgetItem *twi = tw->topLevelItem(i);
if (twi->checkState(0) == Qt::Checked) {
// 添加空格以便正常识别
std::cout << qPrintable(twi->text(m_listPrintColumn)) << " ";
}
}
}
else {
for (auto i: tw->selectedItems()) {
std::cout << qPrintable(i->text(m_listPrintColumn)) << " ";
}
}
std::cout << std::endl;
}
if (m_listPrintColumn == -1) {
printf("%s\n", qPrintable(result.join(sender()->property("Garma_separator").toString())));
}
break;
}
case Forms: {
QFormLayout *fl = sender()->findChild<QFormLayout*>();
QStringList result;
QString format = sender()->property("Garma_date_format").toString();
for (int i = 0; i < fl->count(); ++i) {
if (QLayoutItem *li = fl->itemAt(i, QFormLayout::FieldRole))
result << value(li->widget(), format);
}
printf("%s\n", qPrintable(result.join(sender()->property("Garma_separator").toString())));
break;
}
default:
qDebug() << "unhandled output" << m_type;
break;
}
exit (0);
}
void Garma::quitOnError()
{
exit(1);
}
bool Garma::readGeneral(QStringList &args) {
QStringList remains;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--title") {
m_caption = NEXT_ARG;
} else if (args.at(i) == "--window-icon") {
m_icon = NEXT_ARG;
} else if (args.at(i) == "--width") {
READ_INT(w, UInt, "--width must be followed by a positive number");
m_size.setWidth(w);
} else if (args.at(i) == "--height") {
READ_INT(h, UInt, "--height must be followed by a positive number");
m_size.setHeight(h);
} else if (args.at(i) == "--pos") {
QString pos = NEXT_ARG;
QRegularExpressionMatch m = QRegularExpression("([+-]*[0-9]+)([+-][0-9]+)?").match(pos);
if (m.lastCapturedIndex() > 0 && m.lastCapturedIndex() < 3) {
m_pos.setX(m.captured(1).toInt());
m_pos.setY(m.lastCapturedIndex() == 2 ? m.captured(2).toInt() : 0);
} else {
return !error("--pos must be followed by a position [+-]x[(+-)y]");
}
} else if (args.at(i) == "--timeout") {
READ_INT(t, UInt, "--timeout must be followed by a positive number");
QTimer::singleShot(t*1000, this, SLOT(quit()));
} else if (args.at(i) == "--ok-label") {
m_ok = NEXT_ARG;
} else if (args.at(i) == "--cancel-label") {
m_cancel = NEXT_ARG;
} else if (args.at(i) == "--modal") {
m_modal = true;
} else if (args.at(i) == "--popup") {
m_popup = true;
} else if (args.at(i) == "--attach") {
READ_INT(w, UInt, "--attach must be followed by a positive number");
m_parentWindow = w;
} else if (args.at(i) == "--class") {
m_class = NEXT_ARG;
} else if (args.at(i) == "--name") {
m_name = NEXT_ARG;
} else {
remains << args.at(i);
}
}
args = remains;
return true;
}
char Garma::showCalendar(const QStringList &args)
{
NEW_DIALOG
QDate date = QDate::currentDate();
int d,m,y;
date.getDate(&y, &m, &d);
bool ok;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text") {
vl->addWidget(new QLabel(NEXT_ARG, dlg));
} else if (args.at(i) == "--day") {
d = NEXT_ARG.toUInt(&ok);
if (!ok)
return !error("--day must be followed by a positive number");
} else if (args.at(i) == "--month") {
m = NEXT_ARG.toUInt(&ok);
if (!ok)
return !error("--month must be followed by a positive number");
} else if (args.at(i) == "--year") {
y = NEXT_ARG.toUInt(&ok);
if (!ok)
return !error("--year must be followed by a positive number");
} else if (args.at(i) == "--date-format") {
dlg->setProperty("Garma_date_format", NEXT_ARG);
} else { WARN_UNKNOWN_ARG("--calendar") }
}
date.setDate(y, m, d);
QCalendarWidget *cal = new QCalendarWidget(dlg);
cal->setSelectedDate(date);
vl->addWidget(cal);
connect(cal, SIGNAL(activated(const QDate&)), dlg, SLOT(accept()));
if (!m_popup) {
FINISH_OK_CANCEL_DIALOG
}
SHOW_DIALOG
return 0;
}
char Garma::showEntry(const QStringList &args)
{
DInputDialog *dlg = new DInputDialog;
setDialogIconWithStandard(9, dlg);
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text")
qDebug() << "a";
//dlg->setLabelText(labelText(NEXT_ARG));
else if (args.at(i) == "--entry-text")
dlg->setTextValue(NEXT_ARG);
else if (args.at(i) == "--hide-text")
dlg->setTextEchoMode(QLineEdit::Password);
else if (args.at(i) == "--values") {
dlg->setComboBoxItems(NEXT_ARG.split('|'));
dlg->setComboBoxEditable(true);
} else if (args.at(i) == "--int") {
dlg->setInputMode(DInputDialog::IntInput);
dlg->setIntRange(INT_MIN, INT_MAX);
dlg->setIntValue(NEXT_ARG.toInt());
} else if (args.at(i) == "--float") {
dlg->setInputMode(DInputDialog::DoubleInput);
dlg->setDoubleRange(DBL_MIN, DBL_MAX);
dlg->setDoubleValue(NEXT_ARG.toDouble());
}
else { WARN_UNKNOWN_ARG("--entry") }
}
SHOW_DIALOG
return 0;
}
char Garma::showPassword(const QStringList &args)
{
NEW_DIALOG
setDialogIconWithStandard(58, dlg);
QLineEdit *username(NULL), *password(NULL);
QString prompt = tr("Enter password");
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--username") {
vl->addWidget(new QLabel(tr("Enter username"), dlg));
vl->addWidget(username = new QLineEdit(dlg));
username->setObjectName("Garma_username");
break;
} else if (args.at(i) == "--prompt") {
prompt = NEXT_ARG;
} { WARN_UNKNOWN_ARG("--password") }
}
vl->addWidget(new QLabel(prompt, dlg));
vl->addWidget(password = new QLineEdit(dlg));
password->setObjectName("Garma_password");
password->setEchoMode(QLineEdit::Password);
InputGuard::watch(password);
if (username)
username->setFocus(Qt::OtherFocusReason);
else
password->setFocus(Qt::OtherFocusReason);
FINISH_OK_CANCEL_DIALOG
SHOW_DIALOG
return 0;
}
char Garma::showMessage(const QStringList &args, char type)
{
GMessageBox *dlg = new GMessageBox;
//dlg->setStandardButtons((type == 'q') ? GMessageBox::Yes|GMessageBox::No : GMessageBox::Ok);
QList<GMessageBox::StandardButtons> button;
if (type == 'q') {
button << GMessageBox::No << GMessageBox::Yes;
}
else {
button << GMessageBox::Ok;
}
dlg->setStandardButtonsWithList(button);
// 设置默认文本
dlg->setText(type == 'w' ? tr("Are you sure you want to proceed?") :
(type == 'q' ? tr("Are you sure you want to proceed?") :
(type == 'e' ? tr("An error has occurred.") : tr("All updates are complete."))));
bool wrap = true, html = true;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text")
dlg->setText(html ? labelText(NEXT_ARG) : NEXT_ARG);
else if (args.at(i) == "--icon-name")
dlg->setIconPixmap(QIcon(NEXT_ARG).pixmap(64));
else if (args.at(i) == "--no-wrap")
wrap = false;
else if (args.at(i) == "--ellipsize")
wrap = true;
else if (args.at(i) == "--no-markup")
html = false;
else if (args.at(i) == "--default-cancel")
qDebug() << "a";
//dlg->setDefaultButton(GMessageBox::Cancel);
else if (args.at(i) == "--selectable-labels")
m_selectableLabel = true;
else if (args.at(i).startsWith("--") && args.at(i) != "--info" && args.at(i) != "--question" &&
args.at(i) != "--warning" && args.at(i) != "--error")
qDebug() << "unspecific argument" << args.at(i);
}
if (QLabel *l = dlg->findChild<QLabel*>("qt_msgbox_label")) {
l->setWordWrap(wrap);
l->setTextFormat(html ? Qt::RichText : Qt::PlainText);
if (m_selectableLabel)
l->setTextInteractionFlags(l->textInteractionFlags()|Qt::TextSelectableByMouse);
}
dlg->setIcon(type == 'w' ? GMessageBox::Warning :
(type == 'q' ? GMessageBox::Question :
(type == 'e' ? GMessageBox::Critical : GMessageBox::Information)));
SHOW_DIALOG
return 0;
}
char Garma::showFileSelection(const QStringList &args)
{
DFileDialog *dlg = new DFileDialog;
setDialogIconWithStandard(21, dlg);
QSettings settings("Garma");
dlg->setViewMode(settings.value("FileDetails", false).toBool() ? DFileDialog::Detail : DFileDialog::List);
dlg->setFileMode(DFileDialog::ExistingFile);
dlg->setOption(DFileDialog::DontConfirmOverwrite, false);
dlg->setProperty("Garma_separator", "|");
QVariantList l = settings.value("Bookmarks").toList();
QList<QUrl> bookmarks;
for (int i = 0; i < l.count(); ++i)
bookmarks << l.at(i).toUrl();
if (!bookmarks.isEmpty())
dlg->setSidebarUrls(bookmarks);
QStringList mimeFilters;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--filename") {
QString path = NEXT_ARG;
if (path.endsWith("/."))
dlg->setDirectory(path);
else
dlg->selectFile(path);
}
else if (args.at(i) == "--multiple")
dlg->setFileMode(DFileDialog::ExistingFiles);
else if (args.at(i) == "--directory") {
dlg->setFileMode(DFileDialog::Directory);
dlg->setOption(DFileDialog::ShowDirsOnly);
} else if (args.at(i) == "--save") {
dlg->setFileMode(DFileDialog::AnyFile);
dlg->setAcceptMode(DFileDialog::AcceptSave);
}
else if (args.at(i) == "--separator")
dlg->setProperty("Garma_separator", NEXT_ARG);
else if (args.at(i) == "--confirm-overwrite")
dlg->setOption(DFileDialog::DontConfirmOverwrite);
else if (args.at(i) == "--file-filter") {
QString mimeFilter = NEXT_ARG;
const int idx = mimeFilter.indexOf('|');
if (idx > -1)
mimeFilter = mimeFilter.left(idx).trimmed() + " (" + mimeFilter.mid(idx+1).trimmed() + ")";
mimeFilters << mimeFilter;
}
else { WARN_UNKNOWN_ARG("--file-selection") }
}
dlg->setNameFilters(mimeFilters);
SHOW_DIALOG
return 0;
}
void Garma::toggleItems(QTreeWidgetItem *item, int column)
{
if (column)
return; // not the checkmark
static bool recursion = false;
if (recursion)
return;
recursion = true;
QTreeWidget *tw = item->treeWidget();
for (int i = 0; i < tw->topLevelItemCount(); ++i) {
QTreeWidgetItem *twi = tw->topLevelItem(i);
if (twi != item)
twi->setCheckState(0, Qt::Unchecked);
}
recursion = false;
}
static void addItems(QTreeWidget *tw, QStringList &values, bool editable, bool checkable, bool icons)
{
for (int i = 0; i < values.count(); ) {
QStringList itemValues;
for (int j = 0; j < tw->columnCount(); ++j) {
itemValues << values.at(i++);
if (i == values.count())
break;
}
QTreeWidgetItem *item = new QTreeWidgetItem(tw, itemValues);
Qt::ItemFlags flags = item->flags();
if (editable)
flags |= Qt::ItemIsEditable;
if (checkable) {
flags |= Qt::ItemIsUserCheckable;
// 如果每一项的第一个参数为 true,则代表默认勾选
// 反之 false 则默认不勾选
// 该参数不区分大小写
Qt::CheckState checkState = Qt::Unchecked;
if (itemValues.first().toLower() == "true") {
checkState = Qt::Checked;
}
item->setCheckState(0, checkState);
}
if (icons)
item->setIcon(0, QPixmap(item->text(0)));
if (checkable || icons) {
item->setData(0, Qt::EditRole, item->text(0));
item->setText(0, QString());
}
item->setFlags(flags);
tw->addTopLevelItem(item);
}
}
char Garma::showList(const QStringList &args)
{
NEW_DIALOG
setDialogIconWithStandard(33, dlg);
QLabel *lbl;
vl->addWidget(lbl = new QLabel(dlg));
QTreeWidget *tw;
vl->addWidget(tw = new QTreeWidget(dlg));
tw->setSelectionBehavior(QAbstractItemView::SelectRows);
tw->setSelectionMode(QAbstractItemView::SingleSelection);
tw->setRootIsDecorated(false);
tw->setAllColumnsShowFocus(true);
// 自动根据内容自适应宽度
tw->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
bool editable(false), checkable(false), exclusive(false), icons(false), ok, needFilter(true);
QStringList columns;
QStringList values;
QList<int> hiddenCols;
dlg->setProperty("Garma_separator", "|");
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text")
lbl->setText(labelText(NEXT_ARG));
else if (args.at(i) == "--multiple")
tw->setSelectionMode(QAbstractItemView::ExtendedSelection);
else if (args.at(i) == "--column") {
columns << NEXT_ARG;
} else if (args.at(i) == "--editable")
editable = true;
else if (args.at(i) == "--hide-header")
tw->setHeaderHidden(true);
else if (args.at(i) == "--separator")
dlg->setProperty("Garma_separator", NEXT_ARG);
else if (args.at(i) == "--hide-column") {
int v = NEXT_ARG.toInt(&ok);
if (ok)
hiddenCols << v-1;
} else if (args.at(i) == "--print-column") {
m_listPrintColumn = NEXT_ARG.toInt() - 1;
} else if (args.at(i) == "--checklist") {
tw->setSelectionMode(QAbstractItemView::NoSelection);
tw->setAllColumnsShowFocus(false);
checkable = true;
} else if (args.at(i) == "--radiolist") {
tw->setSelectionMode(QAbstractItemView::NoSelection);
tw->setAllColumnsShowFocus(false);
checkable = true;
exclusive = true;
} else if (args.at(i) == "--imagelist") {
icons = true;
} else if (args.at(i) == "--mid-search") {
if (needFilter) {
needFilter = false;
QLineEdit *filter;
vl->addWidget(filter = new QLineEdit(dlg));
filter->setPlaceholderText(tr("Filter"));
connect (filter, &QLineEdit::textChanged, this, [=](const QString &match){
for (int i = 0; i < tw->topLevelItemCount(); ++i)
tw->topLevelItem(i)->setHidden(!tw->topLevelItem(i)->text(0).contains(match, Qt::CaseInsensitive));
});
}
} else if (args.at(i) != "--list") {
values << args.at(i);
}
}
if (values.isEmpty())
listenToStdIn();
if (checkable)
editable = false;
m_listCheckable = checkable;
// 在非勾选框模式下,允许双击确认
if (!checkable) {
connect(tw, &QTreeWidget::doubleClicked, [dlg](){dlg->done(QDialog::Accepted);});
}
tw->setProperty("Garma_list_flags", int(editable | checkable << 1 | icons << 2));
int columnCount = qMax(columns.count(), 1);
tw->setColumnCount(columnCount);
tw->setHeaderLabels(columns);
foreach (const int &i, hiddenCols)
tw->setColumnHidden(i, true);
addItems(tw, values, editable, checkable, icons);
if (exclusive) {
connect (tw, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(toggleItems(QTreeWidgetItem*, int)));
}
for (int i = 0; i < columns.count(); ++i)
tw->resizeColumnToContents(i);
if (!m_size.isNull()) {
QSize sz = tw->size();
if (m_size.width() > 0)
sz.setWidth(m_size.width());
if (m_size.height() > 0)
sz.setHeight(m_size.height());
tw->setFixedSize(m_size.width(), m_size.height());
}
FINISH_OK_CANCEL_DIALOG
SHOW_DIALOG
return 0;
}
void Garma::notify(const QString message, bool noClose)
{
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.freedesktop.Notifications")) {
QDBusInterface notifications("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
const QString summary = (message.length() < 32) ? message : message.left(25) + "...";
QVariantMap hintMap;
QStringList hintList = m_notificationHints.split(':');
for (int i = 0; i < hintList.count() - 1; i+=2)
hintMap.insert(hintList.at(i), hintList.at(i+1));
QDBusMessage msg = notifications.call("Notify", "Garma", m_notificationId, "dialog-information", summary, message,
QStringList() /*actions*/, hintMap, m_timeout);
if (msg.arguments().count())
m_notificationId = msg.arguments().at(0).toUInt();
return;
}
GMessageBox *dlg = static_cast<GMessageBox*>(m_dialog);
if (!dlg) {
dlg = new GMessageBox;
/*dlg->setIcon(GMessageBox::Information);
dlg->setStandardButtons(noClose ? GMessageBox::NoButton : GMessageBox::Ok);*/
dlg->setWindowFlags(Qt::ToolTip);
dlg->setWindowOpacity(0.8);
if (QLabel *l = dlg->findChild<QLabel*>("qt_msgbox_label")) {
l->setWordWrap(true);
if (m_selectableLabel)
l->setTextInteractionFlags(l->textInteractionFlags()|Qt::TextSelectableByMouse);
}
}
dlg->setText(labelText(message));
SHOW_DIALOG
dlg->adjustSize();
dlg->move(QGuiApplication::screens().at(0)->availableGeometry().topRight() - QPoint(dlg->width() + 20, -20));
}
char Garma::showNotification(const QStringList &args)
{
QString message;
bool listening(false);
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text") {
message = NEXT_ARG;
} else if (args.at(i) == "--listen") {
listening = true;
listenToStdIn();
} else if (args.at(i) == "--hint") {
m_notificationHints = NEXT_ARG;
} else if (args.at(i) == "--selectable-labels") {
m_selectableLabel = true;
} else { WARN_UNKNOWN_ARG("--notification") }
}
if (!message.isEmpty())
notify(message, listening);
if (!(listening || m_dialog))
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
return 0;
}
static QFile *gs_stdin = 0;
void Garma::finishProgress()
{
Q_ASSERT(m_type == Progress);
GProgressDialog *dlg = static_cast<GProgressDialog*>(m_dialog);
if (dlg->property("Garma_autoclose").toBool())
QTimer::singleShot(250, this, SLOT(quit()));
else {
dlg->setRange(0, 100);
dlg->setValue(100);
disconnect (dlg, SIGNAL(canceled()), dlg, SLOT(reject()));
connect (dlg, SIGNAL(canceled()), dlg, SLOT(accept()));
dlg->setCancelButtonText(m_ok.isNull() ? tr("Ok") : m_ok);
dlg->setCloseButtonVisiable(true); // 重新显示启用按钮
if (QPushButton *btn = dlg->findChild<QPushButton*>())
btn->show();
}
}
void Garma::readStdIn()
{
if (!gs_stdin->isOpen()) {
return;
}
QSocketNotifier *notifier = qobject_cast<QSocketNotifier*>(sender());
if (notifier)
notifier->setEnabled(false);
// List 需要一次性加载完成以正常从流读出列表
QByteArray ba = m_type == List ? gs_stdin->readAll() : gs_stdin->readLine();
if (ba.isEmpty() && notifier) {
gs_stdin->close();
// gs_stdin->deleteLater(); // hello segfault...
// gs_stdin = NULL;
notifier->deleteLater();
return;
}
static QString cachedText;
QString newText = QString::fromLocal8Bit(ba);
if (newText.isEmpty() && cachedText.isEmpty()) {
if (notifier)
notifier->setEnabled(true);
return;
}
QStringList input;
if (m_type != TextInfo) {
if (newText.endsWith('\n'))
newText.resize(newText.length()-1);
input = newText.split('\n');
}
if (m_type == Progress) {
GProgressDialog *dlg = static_cast<GProgressDialog*>(m_dialog);
const int oldValue = dlg->value();
bool ok;
foreach (QString line, input) {
if (line.startsWith('#')) {
dlg->setLabelText(labelText(line.mid(1)));
} else {
static const QRegularExpression nondigit("[^0-9]");
int u = line.section(nondigit,0,0).toInt(&ok);
if (ok)
dlg->setValue(qMin(100,u));
}
}
if (dlg->value() == 100) {
finishProgress();
} else if (oldValue == 100) {
disconnect (dlg, SIGNAL(canceled()), dlg, SLOT(accept()));
connect (dlg, SIGNAL(canceled()), dlg, SLOT(reject()));
dlg->setCancelButtonText(m_cancel.isNull() ? tr("Cancel") : m_cancel);
} else if (dlg->property("Garma_eta").toBool()) {
static QDateTime starttime;
if (starttime.isNull()) {
starttime = QDateTime::currentDateTime();
} else if (dlg->value() > 0) {
const qint64 secs = starttime.secsTo(QDateTime::currentDateTime());
QString eta = QTime(0,0,0).addSecs(100 * secs / dlg->value() - secs).toString();
foreach (QWidget *w, dlg->findChildren<QWidget*>())
w->setToolTip(eta);
}
}
} else if (m_type == TextInfo) {
if (QTextEdit *te = m_dialog->findChild<QTextEdit*>()) {
cachedText += newText;
static QPropertyAnimation *animator = NULL;
if (!animator || animator->state() != QPropertyAnimation::Running) {
const int oldValue = te->verticalScrollBar() ? te->verticalScrollBar()->value() : 0;
if (te->property("Garma_html").toBool())
te->setHtml(te->toHtml() + cachedText);
else
te->setPlainText(te->toPlainText() + cachedText);
cachedText.clear();
if (te->verticalScrollBar() && te->property("Garma_autoscroll").toBool()) {
te->verticalScrollBar()->setValue(oldValue);
if (!animator) {
animator = new QPropertyAnimation(te->verticalScrollBar(), "value", this);
animator->setEasingCurve(QEasingCurve::InOutCubic);
connect(animator, SIGNAL(finished()), SLOT(readStdIn()));
}
const int diff = te->verticalScrollBar()->maximum() - oldValue;
if (diff > 0) {
animator->setDuration(qMin(qMax(200, diff), 2500));
animator->setEndValue(te->verticalScrollBar()->maximum());
animator->start();
}
}
}
}
} else if (m_type == Notification) {
bool userNeedsHelp = true;
foreach (QString line, input) {
int split = line.indexOf(':');
if (split < 0)
continue;
if (line.left(split) == "icon") {
userNeedsHelp = false;
// TODO: some icon filename, seems gnome specific and i've no idea how to handle this atm.
qWarning("'icon' command not yet supported - if you know what this is supposed to do, please file a bug");
} else if (line.left(split) == "message" || line.left(split) == "tooltip") {
userNeedsHelp = false;
notify(line.mid(split+1));
} else if (line.left(split) == "visible") {
userNeedsHelp = false;
if (m_dialog)
m_dialog->setVisible(line.mid(split+1).trimmed().compare("false", Qt::CaseInsensitive) &&
line.mid(split+1).trimmed().compare("0", Qt::CaseInsensitive));
else
qWarning("'visible' command only supported for failsafe dialog notification");
} else if (line.left(split) == "hints") {
m_notificationHints = line.mid(split+1);
}
}
if (userNeedsHelp)
qDebug() << "icon: <filename>\nmessage: <UTF-8 encoded text>\ntooltip: <UTF-8 encoded text>\nvisible: <true|false>";
} else if (m_type == List) {
if (QTreeWidget *tw = m_dialog->findChild<QTreeWidget*>()) {
const int twflags = tw->property("Garma_list_flags").toInt();
addItems(tw, input, twflags & 1, twflags & 1<<1, twflags & 1<<2);
}
} else if (m_type == Dzen) {
while (true) {
ba = gs_stdin->read(8192);
if (ba.isEmpty())
break;
newText = QString::fromLocal8Bit(ba);
if (newText.endsWith('\n'))
newText.resize(newText.length()-1);
input.append(newText.split('\n'));
if (ba.size() < 8192) /** @todo: if the input block is exactly 8kB, we're gonna wait for the next one here */
break;
}
// if (input.isEmpty())
// return;
QLabel *header = m_dialog->findChild<QLabel*>("header");
QLabel *body = m_dialog->findChild<QLabel*>("body");
if (body) {
if (header->text().isEmpty() || m_dialog->property("unified").toBool())
header->setText(input.takeFirst());
if (!input.isEmpty()) {
QStringList oldBody = body->text().split('\n');
oldBody.append(input);
const int idx = qMax(0, oldBody.count() - body->property("lines").toInt());
body->setText(oldBody.mid(idx).join('\n'));
}
} else {
header->setText(input.constLast());
}
}
if (notifier)
notifier->setEnabled(true);
QCoreApplication::processEvents();
}
void Garma::exitStdIn()
{
if (m_type == Progress) {
finishProgress();
}
}
void Garma::listenToStdIn()
{
if (gs_stdin)
return;
gs_stdin = new QFile;
if (gs_stdin->open(stdin, QIODevice::ReadOnly)) {
QSocketNotifier *snr = new QSocketNotifier(gs_stdin->handle(), QSocketNotifier::Read, gs_stdin);
connect (snr, &QSocketNotifier::destroyed, this, &Garma::exitStdIn); // 用于监听程序是否退出
connect (snr, SIGNAL(activated(int)), SLOT(readStdIn()));
} else {
delete gs_stdin;
gs_stdin = NULL;
}
}
char Garma::showProgress(const QStringList &args)
{
GProgressDialog *dlg = new GProgressDialog;
dlg->setRange(0, 100);
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text")
dlg->setLabelText(labelText(NEXT_ARG));
else if (args.at(i) == "--percentage")
dlg->setValue(NEXT_ARG.toUInt());
else if (args.at(i) == "--pulsate")
dlg->setRange(0,0);
else if (args.at(i) == "--auto-close")
dlg->setProperty("Garma_autoclose", true);
else if (args.at(i) == "--auto-kill")
dlg->setProperty("Garma_autokill_parent", true);
else if (args.at(i) == "--no-cancel") {
dlg->setCloseButtonVisiable(false);
} else if (args.at(i) == "--time-remaining") {
dlg->setProperty("Garma_eta", true);
}
else { WARN_UNKNOWN_ARG("--progress") }
}
listenToStdIn();
if (dlg->maximum() == 0) { // pulsate, quit as stdin closes
connect (gs_stdin, SIGNAL(aboutToClose()), this, SLOT(finishProgress()));
}
if (!m_cancel.isNull())
dlg->setCancelButtonText(m_cancel);
connect (dlg, SIGNAL(canceled()), dlg, SLOT(reject()));
SHOW_DIALOG
return 0;
}
void Garma::printInteger(int v)
{
printf("%d\n", v);
}
char Garma::showScale(const QStringList &args)
{
NEW_DIALOG
setDialogIconWithStandard(9, dlg);
QHBoxLayout *hl = new QHBoxLayout;
QLabel *lbl, *val;
QSlider *sld;
vl->addWidget(lbl = new QLabel(tr("Enter a value"), dlg));
vl->addLayout(hl);
hl->addWidget(sld = new QSlider(Qt::Horizontal, dlg));
hl->addWidget(val = new QLabel(dlg));
connect (sld, SIGNAL(valueChanged(int)), val, SLOT(setNum(int)));
FINISH_OK_CANCEL_DIALOG
sld->setRange(0,100);
val->setNum(0);
bool ok;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--text")
lbl->setText(labelText(NEXT_ARG));
else if (args.at(i) == "--value")
sld->setValue(NEXT_ARG.toInt());
else if (args.at(i) == "--min-value") {
int v = NEXT_ARG.toInt(&ok);
if (ok)
sld->setMinimum(v);
} else if (args.at(i) == "--max-value") {
int v = NEXT_ARG.toInt(&ok);
if (ok)
sld->setMaximum(v);
} else if (args.at(i) == "--step") {
int u = NEXT_ARG.toInt(&ok);
if (ok)
sld->setSingleStep(u);
} else if (args.at(i) == "--print-partial") {
connect (sld, SIGNAL(valueChanged(int)), SLOT(printInteger(int)));
} else if (args.at(i) == "--hide-value") {
val->hide();
} else { WARN_UNKNOWN_ARG("--scale") }
}
SHOW_DIALOG
return 0;
}
char Garma::showAbout(const QStringList &args)
{
DAboutDialog *dlg = new DAboutDialog;
setDialogIconWithStandard(9, dlg);
for (int i = 0; i < args.count(); ++i) {
QString option = args.at(i);
if (option == "--description") {
dlg->setDescription(NEXT_ARG);
}
else if (option == "--version") {
dlg->setVersion(NEXT_ARG);
}
else if (option == "--acknowledgementLink") {
dlg->setAcknowledgementLink(NEXT_ARG);
}
else if (option == "--license") {
dlg->setLicense(NEXT_ARG);
}
else if (option == "--websiteLink") {
dlg->setWebsiteLink(NEXT_ARG);
}
else if (option == "--icon") {
dlg->setProductIcon(QIcon(NEXT_ARG));
}
else if (option == "--websiteName") {
dlg->setWebsiteName(NEXT_ARG);
}
else if (option == "--title") {
dlg->setTitle(NEXT_ARG);
}
else {
qDebug() << "unspecific argument" << args.at(i);
}
}
SHOW_DIALOG
return 0;
}
char Garma::showText(const QStringList &args)
{
NEW_DIALOG
setDialogIconWithStandard(9, dlg);
QTextBrowser *te;
vl->addWidget(te = new QTextBrowser(dlg));
te->setReadOnly(true);
te->setOpenExternalLinks(true);
QCheckBox *cb(NULL);
QString filename;
bool html(false), plain(false), onlyMarkup(false), url(false);
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--filename") {
filename = NEXT_ARG;
} else if (args.at(i) == "--url") {
filename = NEXT_ARG;
url = true;
}
else if (args.at(i) == "--editable")
te->setReadOnly(false);
else if (args.at(i) == "--font") {
te->setFont(QFont(NEXT_ARG));
} else if (args.at(i) == "--checkbox") {
vl->addWidget(cb = new QCheckBox(NEXT_ARG, dlg));
} else if (args.at(i) == "--auto-scroll") {
te->setProperty("Garma_autoscroll", true);
} else if (args.at(i) == "--html") {
html = true;
te->setProperty("Garma_html", true);
} else if (args.at(i) == "--plain") {
plain = true;
} else if (args.at(i) == "--no-interaction") {
onlyMarkup = true;
} else { WARN_UNKNOWN_ARG("--text-info") }
}
if (html) {
te->setReadOnly(true);
te->setTextInteractionFlags(onlyMarkup ? Qt::TextSelectableByMouse : Qt::TextBrowserInteraction);
}
if (te->isReadOnly()) {
QPalette pal = te->viewport()->palette();
for (int i = 0; i < 3; ++i) { // Disabled, Active, Inactive, Normal
QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
pal.setColor(cg, QPalette::Base, pal.color(cg, QPalette::Window));
pal.setColor(cg, QPalette::Text, pal.color(cg, QPalette::WindowText));
}
te->viewport()->setPalette(pal);
te->viewport()->setAutoFillBackground(false);
te->setFrameStyle(QFrame::NoFrame);
}
if (filename.isNull()) {
listenToStdIn();
} else if (url) {
QProcess *curl = new QProcess;
connect(curl, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [=]() {
te->setText(QString::fromLocal8Bit(curl->readAllStandardOutput()));
delete curl;
});
curl->start("curl", QStringList() << "-L" << "-s" << filename);
} else {
QFile file(filename);
if (file.open(QIODevice::ReadOnly)) {
if (html)
te->setHtml(QString::fromLocal8Bit(file.readAll()));
else if (plain)
te->setPlainText(QString::fromLocal8Bit(file.readAll()));
else
te->setText(QString::fromLocal8Bit(file.readAll()));
file.close();
}
}
if (!m_size.isNull()) {
QSize sz = te->size();
if (m_size.width() > 0)
sz.setWidth(m_size.width());
if (m_size.height() > 0)
sz.setHeight(m_size.height());
te->setFixedSize(m_size.width(), m_size.height());
}
FINISH_OK_CANCEL_DIALOG
// TODO
/*if (cb) {
QPushButton *btn = btns->button(QDialogButtonBox::Ok);
btn->setEnabled(false);
connect(cb, SIGNAL(toggled(bool)), btn, SLOT(setEnabled(bool)));
}*/
SHOW_DIALOG
return 0;
}
char Garma::showColorSelection(const QStringList &args)
{
QColorDialog *dlg = new QColorDialog;
QVariantList l = QSettings("Garma").value("CustomPalette").toList();
for (int i = 0; i < l.count() && i < dlg->customCount(); ++i)
dlg->setCustomColor(i, QColor(l.at(i).toUInt()));
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--color") {
dlg->setCurrentColor(QColor(NEXT_ARG));
} else if (args.at(i) == "--show-palette") {
qWarning("The show-palette parameter is not supported by Garma. Sorry.");
void(0);
} else if (args.at(i) == "--custom-palette") {
if (i+1 < args.count()) {
QString path = NEXT_ARG;
QFile file(path);
if (file.open(QIODevice::ReadOnly)) {
QStringList pal = QString::fromLocal8Bit(file.readAll()).split('\n');
int r, g, b; bool ok; int idx = 0;
for (const QString &line : pal) {
if (idx > 47) break; // sorry :(
QStringList color = line.split(QRegularExpression("\\s+"), SKIP_EMPTY);
if (color.count() < 3) continue;
r = color.at(0).toInt(&ok); if (!ok) continue;
g = color.at(1).toInt(&ok); if (!ok) continue;
b = color.at(2).toInt(&ok); if (!ok) continue;
dlg->setStandardColor(idx++, QColor(r,g,b));
}
while (idx < 48) {
dlg->setStandardColor(idx++, Qt::black);
}
file.close();
} else {
qWarning("Cannot read %s", path.toLocal8Bit().constData());
}
} else {
qWarning("You have to provide a gimp palette (*.gpl)");
}
}{ WARN_UNKNOWN_ARG("--color-selection") }
}
SHOW_DIALOG
return 0;
}
char Garma::showFontSelection(const QStringList &args)
{
QFontDialog *dlg = new QFontDialog;
QString pattern = "%1-%2:%3:%4";
QString sample = "The quick brown fox jumps over the lazy dog";
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--type") {
QStringList types = NEXT_ARG.split(',');
QFontDialog::FontDialogOptions opts;
for (const QString &type : types) {
if (type == "vector") opts |= QFontDialog::ScalableFonts;
if (type == "bitmap") opts |= QFontDialog::NonScalableFonts;
if (type == "fixed") opts |= QFontDialog::MonospacedFonts;
if (type == "variable") opts |= QFontDialog::ProportionalFonts;
}
if (opts) // https://bugreports.qt.io/browse/QTBUG-93473
dlg->setOptions(opts);
dlg->setCurrentFont(QFont()); // also works around the bug :P
} else if (args.at(i) == "--pattern") {
pattern = NEXT_ARG;
if (!pattern.contains("%1"))
qWarning("The output pattern doesn't include a placeholder for the font name...");
} else if (args.at(i) == "--sample") {
sample = NEXT_ARG;
} { WARN_UNKNOWN_ARG("--font-selection") }
}
if (QLineEdit *smpl = dlg->findChild<QLineEdit*>("qt_fontDialog_sampleEdit"))
smpl->setText(sample);
dlg->setProperty("Garma_fontpattern", pattern);
SHOW_DIALOG
return 0;
}
static void buildList(QTreeWidget **tree, QStringList &values, QStringList &columns, bool &showHeader)
{
QTreeWidget *tw = *tree;
if (!tw)
return;
int columnCount = columns.count();
tw->setHeaderHidden(!showHeader);
if (columns.count()) {
tw->setColumnCount(columns.count());
tw->setHeaderLabels(columns);
} else {
columnCount = 1;
}
for (int i = 0; i < values.count(); ) {
QStringList itemValues;
for (int j = 0; j < columnCount; ++j) {
itemValues << values.at(i++);
if (i == values.count())
break;
}
tw->addTopLevelItem(new QTreeWidgetItem(tw, itemValues));
}
for (int i = 0; i < columns.count(); ++i)
tw->resizeColumnToContents(i);
values.clear();
columns.clear();
showHeader = false;
*tree = NULL;
}
char Garma::showForms(const QStringList &args)
{
NEW_DIALOG
setDialogIconWithStandard(9, dlg);
dlg->setProperty("Garma_separator", "|");
QLabel *label;
vl->addWidget(label = new QLabel(dlg));
QFont fnt = label->font();
fnt.setBold(true);
label->setFont(fnt);
QFormLayout *fl;
vl->addLayout(fl = new QFormLayout);
QTreeWidget *lastList = NULL;
QStringList lastListValues, lastListColumns, lastComboValues;
bool lastListHeader(false);
QComboBox *lastCombo = NULL;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "--add-entry") {
fl->addRow(NEXT_ARG, new QLineEdit(dlg));
} else if (args.at(i) == "--add-password") {
QLineEdit *le;
fl->addRow(NEXT_ARG, le = new QLineEdit(dlg));
le->setEchoMode(QLineEdit::Password);
} else if (args.at(i) == "--add-calendar") {
fl->addRow(NEXT_ARG, new QCalendarWidget(dlg));
} else if (args.at(i) == "--add-list") {
buildList(&lastList, lastListValues, lastListColumns, lastListHeader);
fl->addRow(NEXT_ARG, lastList = new QTreeWidget(dlg));
} else if (args.at(i) == "--list-values") {
lastListValues = NEXT_ARG.split('|');
} else if (args.at(i) == "--column-values") {
lastListColumns = NEXT_ARG.split('|');
} else if (args.at(i) == "--add-combo") {
fl->addRow(NEXT_ARG, lastCombo = new QComboBox(dlg));
lastCombo->addItems(lastComboValues);
lastComboValues.clear();
} else if (args.at(i) == "--combo-values") {
lastComboValues = NEXT_ARG.split('|');
if (lastCombo) {
lastCombo->addItems(lastComboValues);
lastComboValues.clear();
lastCombo = NULL;
}
} else if (args.at(i) == "--show-header") {
lastListHeader = true;
} else if (args.at(i) == "--text") {
label->setText(labelText(NEXT_ARG));
} else if (args.at(i) == "--separator") {
dlg->setProperty("Garma_separator", NEXT_ARG);
} else if (args.at(i) == "--forms-date-format") {
dlg->setProperty("Garma_date_format", NEXT_ARG);
} else if (args.at(i) == "--add-checkbox") {
fl->addRow(new QCheckBox(NEXT_ARG, dlg));
} else { WARN_UNKNOWN_ARG("--forms") }
}
buildList(&lastList, lastListValues, lastListColumns, lastListHeader);
FINISH_OK_CANCEL_DIALOG
SHOW_DIALOG
return 0;
}
static QFont xftFont(const QString &pattern)
{
QFont font;
if (pattern.isEmpty())
return font;
/*
plausible subset of https://keithp.com/~keithp/render/Xft.tutorial
<family>-<size>:<name>=<value>...
*/
const QStringList fields = pattern.split(':');
bool ok = false;
int size = -1;
const int split = fields.at(0).lastIndexOf('-');
if (split > 0) size = fields.at(0).mid(split + 1).toUInt(&ok);
font = ok ? QFont(fields.at(0).mid(0, split), size) : QFont(fields.at(0));
for (int i = 1; i < fields.count(); ++i) {
if (fields.at(i) == "light") font.setWeight(QFont::Light);
else if (fields.at(i) == "medium") font.setWeight(QFont::Medium);
else if (fields.at(i) == "demibold") font.setWeight(QFont::DemiBold);
else if (fields.at(i) == "bold") font.setWeight(QFont::Bold);
else if (fields.at(i) == "black") font.setWeight(QFont::Black);
else if (fields.at(i) == "roman") font.setItalic(false);
else if (fields.at(i) == "italic") font.setItalic(true);
else if (fields.at(i) == "oblique") font.setItalic(true);
else if (fields.at(i).contains('=')) {
QStringList field = fields.at(i).split('=');
if (field.count() < 2) continue;
if (field.at(0) == "family") font.setFamily(field.at(1));
else if (field.at(0) == "weight") font.setWeight(QFont::Weight(field.at(1).toUInt()));
else if (field.at(0) == "size") font.setPointSizeF(field.at(1).toFloat());
else if (field.at(0) == "pixelsize") font.setPixelSize(field.at(1).toUInt());
else if (field.at(0) == "slant") {
if (field.at(0) == "italic" || field.at(0) == "oblique")
font.setItalic(true);
}
}
}
return font;
}
char Garma::showDzen(const QStringList &args)
{
// m_popup = true;
NEW_DIALOG
vl->setContentsMargins(0, 0, 0, 0);
QLabel *header, *body;
vl->addWidget(header = new QLabel(dlg));
header->setObjectName("header");
header->setAlignment(Qt::AlignCenter);
vl->addWidget(body = new QLabel(dlg));
body->setObjectName("body");
QPalette pal = dlg->palette();
if (m_pos.x() == INT_MAX)
m_pos = QPoint(0,0);
int suicide = 0;
for (int i = 0; i < args.count(); ++i) {
if (args.at(i) == "-fg") {
QColor c(NEXT_ARG);
for (int i = 0; i < 3; ++i) { // Disabled, Active, Inactive, Normal
QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
pal.setColor(cg, QPalette::Text, c);
pal.setColor(cg, QPalette::WindowText, c);
}
} else if (args.at(i) == "-bg") {
QColor c(NEXT_ARG);
for (int i = 0; i < 3; ++i) { // Disabled, Active, Inactive, Normal
QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
pal.setColor(cg, QPalette::Base, c);
pal.setColor(cg, QPalette::Window, c);
}
} else if (args.at(i) == "-bg") {
QColor c(NEXT_ARG);
for (int i = 0; i < 3; ++i) { // Disabled, Active, Inactive, Normal
QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
pal.setColor(cg, QPalette::Base, c);
pal.setColor(cg, QPalette::Window, c);
}
} else if (args.at(i) == "-fn") {
dlg->setFont(xftFont(NEXT_ARG));
} else if (args.at(i) == "-ta" || args.at(i) == "-sa") {
QLabel *label = args.at(i) == "-sa" ? body : header;
QString align = NEXT_ARG;
if (align.startsWith('l', Qt::CaseInsensitive))
label->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
else if (align.startsWith('c', Qt::CaseInsensitive))
label->setAlignment(Qt::AlignCenter);
else if (align.startsWith('r', Qt::CaseInsensitive))
label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
} else if (args.at(i) == "-l") {
READ_INT(lines, UInt, "-l(ines) expects a positive integer as next value");
body->setProperty("lines", lines);
} else if (args.at(i) == "-x") {
READ_INT(x, UInt, "-x expects a positive integer as next value");
m_pos.setX(x);
} else if (args.at(i) == "-y") {
READ_INT(y, UInt, "-y expects a positive integer as next value");
m_pos.setY(y);
} else if (args.at(i) == "-w") {
READ_INT(w, UInt, "-w expects a positive integer as next value");
m_size.setWidth(w);
} else if (args.at(i) == "-l") {
READ_INT(lines, UInt, "-l(ines) expects a positive integer as next value");
body->setProperty("lines", lines);
} else if (args.at(i) == "-p") {
suicide = -1;
if (i+1 < args.count()) {
bool ok;
suicide = QString(args.at(i+1)).toUInt(&ok);
if (ok)
++i;
else
suicide = -1;
}
} else if (args.at(i) == "-u") {
dlg->setProperty("unified", true);
} else { WARN_UNKNOWN_ARG("--dzen") }
}
if (!body->property("lines").isValid())
delete body;
dlg->setPalette(pal);
// 62 -tw title window width
// 65 -e events and actions, see (2)
// 66 -m menu mode, see (3)
// 72 -h line height (default: fontheight + 2 pixels)
// 74 -xs number of Xinerama screen
listenToStdIn();
if (suicide > -1)
connect (gs_stdin, &QFile::aboutToClose, this, [=](){
QTimer::singleShot(suicide*1000, this, SLOT(quit()));
});
dlg->setWindowFlags(Qt::BypassWindowManagerHint);
SHOW_DIALOG
return 0;
}
QString Garma::labelText(const QString &s) const
{
// zenity uses pango markup, https://developer.gnome.org/pygtk/stable/pango-markup-language.html
// This near-html-subset isn't really compatible w/ Qt's html subset and we end up
// w/ a weird mix of ASCII escape codes and html tags
// the below is NOT a perfect translation
// known "caveats"
// pango termiantes the string for "\0" (we do not - atm)
// pango inserts some control char for "\f", but that's not reasonably handled by gtk label (so it's ignored here)
if (m_zenity) {
QString r = s;
// First replace backslashes with alarms to avoid false positives below.
// The alarm is treated as invalid and not supported by zenity/pango either
r.replace("\\\\", "\a") \
.replace("\\n", "<br>").replace("\\t", "&nbsp;&nbsp;&nbsp;") \
.replace("\\r", "<br>");
int idx = 0;
while (true) {
static const QRegularExpression octet("\\\\([0-9]{1,3})");
idx = r.indexOf(octet, idx);
if (idx < 0)
break;
int sz = 0;
while (sz < 3 && r.at(idx+sz+1).isDigit())
++sz;
r.replace(idx, sz+1, QChar(r.mid(idx+1, sz).toUInt(nullptr, 8)));
}
r.remove("\\").replace(("\a"), "\\");
return r;
}
return s;
}
void Garma::printHelp(const QString &category)
{
static HelpDict helpDict;
if (helpDict.isEmpty()) {
helpDict["help"] = CategoryHelp(tr("Help options"), HelpList() <<
Help("-h, --help", tr("Show help options")) <<
Help("--help-all", tr("Show all help options")) <<
Help("--help-general", tr("Show general options")) <<
Help("--help-calendar", tr("Show calendar options")) <<
Help("--help-entry", tr("Show text entry options")) <<
Help("--help-error", tr("Show error options")) <<
Help("--help-info", tr("Show info options")) <<
Help("--help-file-selection", tr("Show file selection options")) <<
Help("--help-list", tr("Show list options")) <<
Help("--help-notification", tr("Show notification icon options")) <<
Help("--help-progress", tr("Show progress options")) <<
Help("--help-question", tr("Show question options")) <<
Help("--help-warning", tr("Show warning options")) <<
Help("--help-scale", tr("Show scale options")) <<
Help("--help-text-info", tr("Show text information options")) <<
Help("--help-color-selection", tr("Show color selection options")) <<
Help("--help-password", tr("Show password dialog options")) <<
Help("--help-forms", tr("Show forms dialog options")) <<
Help("--help-misc", tr("Show miscellaneous options")) <<
Help("--help-qt", tr("Show Qt Options")));
helpDict["general"] = CategoryHelp(tr("General options"), HelpList() <<
Help("--title=TITLE", tr("Set the dialog title")) <<
Help("--window-icon=ICONPATH", tr("Set the window icon")) <<
Help("--width=WIDTH", tr("Set the width")) <<
Help("--height=HEIGHT", tr("Set the height")) <<
Help("--pos=[+-]x[(+-)y]", "Garma ONLY! " + tr("Set the position")) <<
Help("--timeout=TIMEOUT", tr("Set dialog timeout in seconds")) <<
Help("--ok-label=TEXT", tr("Sets the label of the Ok button")) <<
Help("--cancel-label=TEXT", tr("Sets the label of the Cancel button")) <<
Help("--modal", tr("Set the modal hint")) <<
Help("--popup", "Garma ONLY! " + tr("Open dialog as unframed and trasient popup window")) <<
Help("--attach=WINDOW", tr("Set the parent window to attach to")));
helpDict["calendar"] = CategoryHelp(tr("Calendar options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--day=DAY", tr("Set the calendar day")) <<
Help("--month=MONTH", tr("Set the calendar month")) <<
Help("--year=YEAR", tr("Set the calendar year")) <<
Help("--timeout=TIMEOUT", tr("Set dialog timeout in seconds")) <<
Help("--date-format=PATTERN", tr("Set the format for the returned date")));
helpDict["entry"] = CategoryHelp(tr("Text entry options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--entry-text=TEXT", tr("Set the entry text")) <<
Help("--hide-text", tr("Hide the entry text")) <<
Help("--values=v1|v2|v3|...", "Garma ONLY! " + tr("Offer preset values to pick from")) <<
Help("--int=integer", "Garma ONLY! " + tr("Integer input only, preset given value")) <<
Help("--float=floating_point", "Garma ONLY! " + tr("Floating point input only, preset given value")));
helpDict["error"] = CategoryHelp(tr("Error options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--icon-name=ICON-NAME", tr("Set the dialog icon")) <<
Help("--no-wrap", tr("Do not enable text wrapping")) <<
Help("--no-markup", tr("Do not enable html markup")) <<
Help("--ellipsize", tr("Do wrap text, zenity has a rather special problem here")) <<
Help("--selectable-labels", "Garma ONLY! " + tr("Allow to select text for copy and paste")));
helpDict["info"] = CategoryHelp(tr("Info options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--icon-name=ICON-NAME", tr("Set the dialog icon")) <<
Help("--no-wrap", tr("Do not enable text wrapping")) <<
Help("--no-markup", tr("Do not enable html markup")) <<
Help("--ellipsize", tr("Do wrap text, zenity has a rather special problem here")) <<
Help("--selectable-labels", "Garma ONLY! " + tr("Allow to select text for copy and paste")));
helpDict["file-selection"] = CategoryHelp(tr("File selection options"), HelpList() <<
Help("--filename=FILENAME", tr("Set the filename")) <<
Help("--multiple", tr("Allow multiple files to be selected")) <<
Help("--directory", tr("Activate directory-only selection")) <<
Help("--save", tr("Activate save mode")) <<
Help("--separator=SEPARATOR", tr("Set output separator character")) <<
Help("--confirm-overwrite", tr("Confirm file selection if filename already exists")) <<
Help("--file-filter=NAME | PATTERN1 PATTERN2 ...", tr("Sets a filename filter")));
helpDict["list"] = CategoryHelp(tr("List Command\n %1 --list [Options] [Item1 ...]\nList Options").arg(applicationName()), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--column=COLUMN", tr("Set the column header")) <<
Help("--checklist", tr("Use check boxes for first column")) <<
Help("--radiolist", tr("Use radio buttons for first column")) <<
Help("--imagelist", tr("Use an image for first column")) <<
Help("--separator=SEPARATOR", tr("Set output separator character")) <<
Help("--multiple", tr("Allow multiple rows to be selected")) <<
Help("--editable", tr("Allow changes to text")) <<
Help("--print-column=NUMBER", tr("Print a specific column (Default is 1. 'ALL' can be used to print all columns)")) <<
Help("--hide-column=NUMBER", tr("Hide a specific column")) <<
Help("--hide-header", tr("Hides the column headers")) <<
Help("--mid-search", tr("Change list default search function searching for text in the middle, not on the beginning")));
helpDict["notification"] = CategoryHelp(tr("Notification icon options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--listen", tr("Listen for commands on stdin")) <<
Help("--hint=TEXT", tr("Set the notification hints")) <<
Help("--selectable-labels", "Garma ONLY! " + tr("Allow to select text for copy and paste")));
helpDict["progress"] = CategoryHelp(tr("Progress options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--percentage=PERCENTAGE", tr("Set initial percentage")) <<
Help("--pulsate", tr("Pulsate progress bar")) <<
Help("--auto-close", tr("Dismiss the dialog when 100% has been reached")) <<
Help("--auto-kill", tr("Kill parent process if Cancel button is pressed")) <<
Help("--no-cancel", tr("Hide Cancel button")));
helpDict["question"] = CategoryHelp(tr("Question options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--icon-name=ICON-NAME", tr("Set the dialog icon")) <<
Help("--no-wrap", tr("Do not enable text wrapping")) <<
Help("--no-markup", tr("Do not enable html markup")) <<
Help("--default-cancel", tr("Give cancel button focus by default")) <<
Help("--ellipsize", tr("Do wrap text, zenity has a rather special problem here")) <<
Help("--selectable-labels", "Garma ONLY! " + tr("Allow to select text for copy and paste")));
helpDict["warning"] = CategoryHelp(tr("Warning options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--icon-name=ICON-NAME", tr("Set the dialog icon")) <<
Help("--no-wrap", tr("Do not enable text wrapping")) <<
Help("--no-markup", tr("Do not enable html markup")) <<
Help("--ellipsize", tr("Do wrap text, zenity has a rather special problem here")) <<
Help("--selectable-labels", "Garma ONLY! " + tr("Allow to select text for copy and paste")));
helpDict["scale"] = CategoryHelp(tr("Scale options"), HelpList() <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--value=VALUE", tr("Set initial value")) <<
Help("--min-value=VALUE", tr("Set minimum value")) <<
Help("--max-value=VALUE", tr("Set maximum value")) <<
Help("--step=VALUE", tr("Set step size")) <<
Help("--print-partial", tr("Print partial values")) <<
Help("--hide-value", tr("Hide value")));
helpDict["text-info"] = CategoryHelp(tr("Text information options"), HelpList() <<
Help("--filename=FILENAME", tr("Open file")) <<
Help("--editable", tr("Allow changes to text")) <<
Help("--font=TEXT", tr("Set the text font")) <<
Help("--checkbox=TEXT", tr("Enable an I read and agree checkbox")) <<
Help("--plain", "Garma ONLY! " + tr("Force plain text, zenity default limitation")) <<
Help("--html", tr("Enable HTML support")) <<
Help("--no-interaction", tr("Do not enable user interaction with the WebView. Only works if you use --html option")) <<
Help("--url=URL", "REQUIRES CURL BINARY! " + tr("Set an URL instead of a file. Only works if you use --html option")) <<
Help("--auto-scroll", tr("Auto scroll the text to the end. Only when text is captured from stdin")));
helpDict["color-selection"] = CategoryHelp(tr("Color selection options"), HelpList() <<
Help("--color=VALUE", tr("Set the color")) <<
Help("--show-palette", tr("Show the palette")) <<
Help("--custom-palette=path/to/some.gpl", "Garma ONLY! " + tr("Load a custom GPL for standard colors")));
helpDict["font-selection"] = CategoryHelp(tr("Font selection options"), HelpList() <<
Help("--type=[vector][,bitmap][,fixed][,variable]", tr("Filter fonts (default: all)")) <<
Help("--pattern=%1-%2:%3:%4", tr("Output pattern, %1: Name, %2: Size, %3: weight, %4: slant")) <<
Help("--sample=TEXT", tr("Sample text, defaults to the foxdogthing")));
helpDict["password"] = CategoryHelp(tr("Password dialog options"), HelpList() <<
Help("--username", tr("Display the username option")) <<
Help("--prompt=TEXT", "Garma ONLY! " + tr("The prompt for the user")));
helpDict["forms"] = CategoryHelp(tr("Forms dialog options"), HelpList() <<
Help("--add-entry=Field name", tr("Add a new Entry in forms dialog")) <<
Help("--add-password=Field name", tr("Add a new Password Entry in forms dialog")) <<
Help("--add-calendar=Calendar field name", tr("Add a new Calendar in forms dialog")) <<
Help("--add-list=List field and header name", tr("Add a new List in forms dialog")) <<
Help("--list-values=List of values separated by |", tr("List of values for List")) <<
Help("--column-values=List of values separated by |", tr("List of values for columns")) <<
Help("--add-combo=Combo box field name", tr("Add a new combo box in forms dialog")) <<
Help("--combo-values=List of values separated by |", tr("List of values for combo box")) <<
Help("--show-header", tr("Show the columns header")) <<
Help("--text=TEXT", tr("Set the dialog text")) <<
Help("--separator=SEPARATOR", tr("Set output separator character")) <<
Help("--forms-date-format=PATTERN", tr("Set the format for the returned date")) <<
Help("--add-checkbox=Checkbox label", "Garma ONLY! " + tr("Add a new Checkbox forms dialog")));
helpDict["misc"] = CategoryHelp(tr("Miscellaneous options"), HelpList() <<
Help("--about", tr("About Garma")) <<
Help("--version", tr("Print version")));
helpDict["qt"] = CategoryHelp(tr("Qt options"), HelpList() <<
Help("--foo", tr("Foo")) <<
Help("--bar", tr("Bar")));
helpDict["application"] = CategoryHelp(tr("Application Options"), HelpList() <<
Help("--calendar", tr("Display calendar dialog")) <<
Help("--entry", tr("Display text entry dialog")) <<
Help("--error", tr("Display error dialog")) <<
Help("--info", tr("Display info dialog")) <<
Help("--file-selection", tr("Display file selection dialog")) <<
Help("--list", tr("Display list dialog")) <<
Help("--notification", tr("Display notification")) <<
Help("--progress", tr("Display progress indication dialog")) <<
Help("--question", tr("Display question dialog")) <<
Help("--warning", tr("Display warning dialog")) <<
Help("--scale", tr("Display scale dialog")) <<
Help("--text-info", tr("Display text information dialog")) <<
Help("--color-selection", tr("Display color selection dialog")) <<
Help("--font-selection", "Garma ONLY! " + tr("Display font selection dialog")) <<
Help("--password", tr("Display password dialog")) <<
Help("--forms", tr("Display forms dialog")) <<
Help("--display=DISPLAY", tr("X display to use")) <<
Help("--class=CLASS", tr("Program class as used by the window manager")) <<
Help("--name=NAME", tr("Program name as used by the window manager")));
}
if (category == "all") {
foreach(const CategoryHelp &el, helpDict) {
printf("%s\n", qPrintable(el.first));
foreach (const Help &help, el.second)
printf(" %-53s%s\n", qPrintable(help.first), qPrintable(help.second));
printf("\n");
}
return;
}
HelpDict::const_iterator it = helpDict.constEnd();
if (!category.isEmpty())
it = helpDict.find(category);
if (it == helpDict.constEnd()) {
printf("Usage:\n %s [OPTION ...]\n\n", qPrintable(applicationName()));
printHelp("help");
printHelp("application");
return;
}
printf("%s\n", qPrintable(it->first));
foreach (const Help &help, it->second)
printf(" %-53s%s\n", qPrintable(help.first), qPrintable(help.second));
printf("\n");
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/GXDE-OS/garma.git
git@gitee.com:GXDE-OS/garma.git
GXDE-OS
garma
garma
master

搜索帮助